From 3db74ce483cb3ba39db275620d87cce0cb701160 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Mon, 10 Jan 2022 14:30:42 -0800 Subject: [PATCH 001/165] [AD-509] Update mac developer environment setup --- README.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a52f6cf3d..642c44660 100644 --- a/README.md +++ b/README.md @@ -19,23 +19,31 @@ 3. [WiX Installer (3.11)](https://wixtoolset.org/releases/) 1. Ensure to add path to WiX executables (e.g. `C:\Program Files (x86)\WiX Toolset v3.11\bin`) 4. Java **JDK** (version 8+ - 17 recommended) - 1. Ensure to set JAVA_HOME -5. Run one of build scripts to create an initial compilation. + 1. Ensure to set JAVA_HOME. +5. Boost Test Framework + 1. Install via [VCPKG](https://vcpkg.io/en/getting-started.html) using `.\vcpkg install openssl:x64-windows boost-test:x64-windows boost-asio:x64-windows boost-chrono:x64-windows boost-interprocess:x64-windows boost-regex:x64-windows boost-system:x64-windows boost-thread:x64-windows` +6. Run one of the build scripts to create an initial compilation. 1. E.g.: `.\build_win_debug64.ps1` 2. Navigate to the `build\odbc\cmake` folder to use the generated solution file, `Ignite.C++.sln` to work on source code development and testing. -6. More details in `src\DEVNOTES.txt`. +7. More details in `src\DEVNOTES.txt`. ### MacOS -1. Install deppendencies - 1. brew install cmake - 2. brew install openssl - 3. brew install unixodbc -2. Run one of build scripts to create an initial compilation. - 1. E.g.: `./buid_mac_release64.sh` +1. Install dependencies + 1. `brew install cmake` + 2. `brew install openssl` + 3. `brew install unixodbc` + - You may need to unlink `libiodbc` if you already have this installed. Use `brew unlink libiodbc`. + 4. `brew install boost` + 5. Install Java **JDK** (version 8+ - 17 recommended) + - This can be done through Homebrew using `brew install --cask temurin`. + - Ensure to set `JAVA_HOME`. +2. Run one of the build scripts to create an initial compilation. + 1. E.g.: `./build_mac_release64.sh` 2. Navigate to the `build/odbc/lib` folder to use the generated files. 3. Use Microsoft VS Code to work on source code devlopment and testing. +4. More details in `src\DEVNOTES.txt`. ### Linux From 52b9b0272b62f20c50d399bf7d5188d89c0262e9 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Mon, 10 Jan 2022 14:31:48 -0800 Subject: [PATCH 002/165] Adjust formatting --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 642c44660..46b591555 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ 3. [WiX Installer (3.11)](https://wixtoolset.org/releases/) 1. Ensure to add path to WiX executables (e.g. `C:\Program Files (x86)\WiX Toolset v3.11\bin`) 4. Java **JDK** (version 8+ - 17 recommended) - 1. Ensure to set JAVA_HOME. + 1. Ensure to set `JAVA_HOME`. 5. Boost Test Framework 1. Install via [VCPKG](https://vcpkg.io/en/getting-started.html) using `.\vcpkg install openssl:x64-windows boost-test:x64-windows boost-asio:x64-windows boost-chrono:x64-windows boost-interprocess:x64-windows boost-regex:x64-windows boost-system:x64-windows boost-thread:x64-windows` 6. Run one of the build scripts to create an initial compilation. @@ -42,7 +42,7 @@ 2. Run one of the build scripts to create an initial compilation. 1. E.g.: `./build_mac_release64.sh` 2. Navigate to the `build/odbc/lib` folder to use the generated files. -3. Use Microsoft VS Code to work on source code devlopment and testing. +3. Use Microsoft VS Code to work on source code development and testing. 4. More details in `src\DEVNOTES.txt`. ### Linux From d3278a4343fcfb048545b465d85ea8869c7eca3c Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Wed, 12 Jan 2022 15:11:21 -0800 Subject: [PATCH 003/165] Add note about llvm --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 46b591555..2b80f53d9 100644 --- a/README.md +++ b/README.md @@ -38,12 +38,13 @@ 4. `brew install boost` 5. Install Java **JDK** (version 8+ - 17 recommended) - This can be done through Homebrew using `brew install --cask temurin`. - - Ensure to set `JAVA_HOME`. + - Ensure to set `JAVA_HOME`. + 6. If creating a debug build (`./build_mac_debug64.sh`), install LLVM. + - To ensure LLVM and CMake are compatible, use the LLVM included with XCode by modifying the PATH with `export PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/:$PATH`. 2. Run one of the build scripts to create an initial compilation. 1. E.g.: `./build_mac_release64.sh` 2. Navigate to the `build/odbc/lib` folder to use the generated files. -3. Use Microsoft VS Code to work on source code development and testing. -4. More details in `src\DEVNOTES.txt`. +3. More details in `src\DEVNOTES.txt`. ### Linux From 9802e1b6c21168ad5d53736ea041824e7dd41b09 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Fri, 14 Jan 2022 10:49:02 -0800 Subject: [PATCH 004/165] Add note about iodbc --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index 2b80f53d9..221589bb9 100644 --- a/README.md +++ b/README.md @@ -49,3 +49,15 @@ ### Linux TBD + +### Troubleshooting + +#### Issue: MacOS build fails with error about iODBC header +##### Example error message +``` +/Library/Frameworks/iODBC.framework/Headers/sqlext.h:82:10: fatal error: 'iODBC/sql.h' file not found +#include + ^~~~~~~~~~~~~ +``` +##### Fix +If you have installed the iODBC Driver Manager, the headers installed with it might be used instead of those from `unixodbc`. You may need to uninstall this driver manager and remove the `/Library/Frameworks/iODBC.framework/` directory. \ No newline at end of file From dfc1d5e5bcdc5fe5252974566421bc58692dc135 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" <96995091+alinaliBQ@users.noreply.github.com> Date: Fri, 14 Jan 2022 15:33:38 -0800 Subject: [PATCH 005/165] Update README.md change the install options for OpenSSL, since vcpkg is a preferred option --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 221589bb9..743f8ab34 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ 6. Wix Toolset v4 Schemas for Visual Studio 7. WiX Toolset Visual Studio 2019 Extension 2. OpenSSL (full) - 1. Installed via [Chocolatey](https://community.chocolatey.org/packages/openssl). - 2. Or installed via [VCPKG](https://vcpkg.io/en/getting-started.html) (`.\vcpkg install openssl`). + 1. Installed via [VCPKG](https://vcpkg.io/en/getting-started.html) (`.\vcpkg install openssl`). + 2. Or installed via [Chocolatey](https://community.chocolatey.org/packages/openssl). 3. Ensure to set the OPENSSL_ROOT_DIR. 3. [WiX Installer (3.11)](https://wixtoolset.org/releases/) 1. Ensure to add path to WiX executables (e.g. `C:\Program Files (x86)\WiX Toolset v3.11\bin`) @@ -60,4 +60,4 @@ TBD ^~~~~~~~~~~~~ ``` ##### Fix -If you have installed the iODBC Driver Manager, the headers installed with it might be used instead of those from `unixodbc`. You may need to uninstall this driver manager and remove the `/Library/Frameworks/iODBC.framework/` directory. \ No newline at end of file +If you have installed the iODBC Driver Manager, the headers installed with it might be used instead of those from `unixodbc`. You may need to uninstall this driver manager and remove the `/Library/Frameworks/iODBC.framework/` directory. From 14f8011342476b53bb9fe9144fcc25c50ffb1622 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" <96995091+alinaliBQ@users.noreply.github.com> Date: Mon, 17 Jan 2022 10:06:46 -0800 Subject: [PATCH 006/165] Update README.md remove the WiX Toolset v4 requirement --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 743f8ab34..c0757ccd7 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,7 @@ 3. C++ ATL for latest v142 build tools (x86 & x64) 4. C++ MFC for latest v142 build tools (x86 & x64) 5. WiX Toolset v3 Schemas for Visual Studio - 6. Wix Toolset v4 Schemas for Visual Studio - 7. WiX Toolset Visual Studio 2019 Extension + 6. WiX Toolset Visual Studio 2019 Extension 2. OpenSSL (full) 1. Installed via [VCPKG](https://vcpkg.io/en/getting-started.html) (`.\vcpkg install openssl`). 2. Or installed via [Chocolatey](https://community.chocolatey.org/packages/openssl). From d6ccf0e66af0fe78c367493b2fe56f038bd5d801 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 17 Jan 2022 15:52:29 -0800 Subject: [PATCH 007/165] Update README.md add steps for the fix for ignite-odbc-tests.profraw error in README. --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c0757ccd7..cb1308e83 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,9 @@ 5. Install Java **JDK** (version 8+ - 17 recommended) - This can be done through Homebrew using `brew install --cask temurin`. - Ensure to set `JAVA_HOME`. - 6. If creating a debug build (`./build_mac_debug64.sh`), install LLVM. - - To ensure LLVM and CMake are compatible, use the LLVM included with XCode by modifying the PATH with `export PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/:$PATH`. + 6. If creating a debug build (`./build_mac_debug64.sh`), LLVM is required. + - If you only have XCode Command Line Tools, use the LLVM included with XCode by modifying the PATH with `export PATH=/Library/Developer/CommandLineTools/usr/bin/:$PATH`. Ensure this XCode path comes first in $PATH. If error occurs, check that clang and llvm are under folder Library/Developer/CommandLineTools/usr/bin. + - If you have XCode application, to ensure LLVM and CMake are compatible, use the LLVM included with XCode by modifying the PATH with `export PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/:$PATH`. 2. Run one of the build scripts to create an initial compilation. 1. E.g.: `./build_mac_release64.sh` 2. Navigate to the `build/odbc/lib` folder to use the generated files. From eda56ebe585d6e89e862b741d1e4ae4d95d51055 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Tue, 18 Jan 2022 12:39:18 -0800 Subject: [PATCH 008/165] [AD-517] Remove old properties + add new properties --- .../ignite/odbc/config/configuration.h | 570 ++++++++++++------ .../odbc/config/connection_string_parser.h | 76 ++- .../system/ui/dsn_configuration_window.cpp | 98 +-- src/odbc/src/config/configuration.cpp | 408 ++++++++----- .../src/config/connection_string_parser.cpp | 269 +++++---- src/odbc/src/connection.cpp | 27 +- src/odbc/src/dsn_config.cpp | 137 +++-- src/odbc/src/message.cpp | 6 +- src/odbc/src/query/batch_query.cpp | 2 +- src/odbc/src/query/data_query.cpp | 6 +- 10 files changed, 986 insertions(+), 613 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index 69f41b317..c5a021c2d 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -53,58 +53,91 @@ namespace ignite static const std::string driver; /** Default value for schema attribute. */ - static const std::string schema; + static const std::string database; /** Default value for address attribute. */ static const std::string address; /** Default value for server attribute. */ - static const std::string server; + static const std::string hostname; + + /** Default value for port attribute. */ + static const uint16_t port; + + /** Default value for user attribute. */ + static const std::string user; + + /** Default value for password attribute. */ + static const std::string password; + + /** Default value for appName attribute. */ + static const std::string appName; + + /** Default value for loginTimeoutSec attribute. */ + static const int32_t loginTimeoutSec; + + /** Default value for readPreference attribute. */ + static const std::string readPreference; + + /** Default value for replicaSet attribute. */ + static const std::string replicaSet; + + /** Default value for retryReads attribute. */ + static const bool retryReads; /** Default value for sslMode attribute. */ static const ssl::SslMode::Type sslMode; - /** Default value for sslKeyFile attribute. */ - static const std::string sslKeyFile; + /** Default value for tls attribute. */ + static const bool tls; - /** Default value for sslCertFile attribute. */ - static const std::string sslCertFile; + /** Default value for tlsAllowInvalidHostnames attribute. */ + static const bool tlsAllowInvalidHostnames; - /** Default value for sslCaFile attribute. */ - static const std::string sslCaFile; + /** Default value for tlsCaFile attribute. */ + static const std::string tlsCaFile; - /** Default value for protocol version. */ - static const ProtocolVersion& protocolVersion; + /** Default value for sshUser attribute. */ + static const std::string sshUser; - /** Default value for port attribute. */ - static const uint16_t port; + /** Default value for sshHost attribute. */ + static const std::string sshHost; - /** Default value for fetch results page size attribute. */ - static const int32_t pageSize; + /** Default value for sshPrivateKeyFile attribute. */ + static const std::string sshPrivateKeyFile; - /** Default value for distributed joins attribute. */ - static const bool distributedJoins; + /** Default value for sshPrivateKeyPassphrase attribute. */ + static const std::string sshPrivateKeyPassphrase; - /** Default value for enforce join order attribute. */ - static const bool enforceJoinOrder; + /** Default value for sshStrictHostKeyChecking attribute. */ + static const bool sshStrictHostKeyChecking; - /** Default value for replicated only attribute. */ - static const bool replicatedOnly; + /** Default value for sshKnownHostsFile attribute. */ + static const std::string sshKnownHostsFile; - /** Default value for collocated attribute. */ - static const bool collocated; + /** Default value for scanMethod attribute. */ + static const std::string scanMethod; - /** Default value for lazy attribute. */ - static const bool lazy; + /** Default value for scanLimit attribute. */ + static const int32_t scanLimit; - /** Default value for skipReducerOnUpdate attribute. */ - static const bool skipReducerOnUpdate; + /** Default value for schemaName attribute. */ + static const std::string schemaName; - /** Default value for user attribute. */ - static const std::string user; + /** Default value for refreshSchema attribute. */ + static const bool refreshSchema; - /** Default value for password attribute. */ - static const std::string password; + /** Default value for sslKeyFile attribute. */ + static const std::string sslKeyFile; + + /** Default value for sslCertFile attribute. */ + static const std::string sslCertFile; + + /** Default value for protocol version. */ + // static const ProtocolVersion& protocolVersion; + + /** Default value for fetch results page size attribute. */ + static const int32_t defaultFetchSize; /** Default value for nestedTxMode attribute. */ static const NestedTxMode::Type nestedTxMode; @@ -127,27 +160,6 @@ namespace ignite */ std::string ToConnectString() const; - /** - * Get server port. - * - * @return Server port. - */ - uint16_t GetTcpPort() const; - - /** - * Set server port. - * - * @param port Server port. - */ - void SetTcpPort(uint16_t port); - - /** - * Check if the value set. - * - * @return @true if the value set. - */ - bool IsTcpPortSet() const; - /** * Get DSN. * @@ -188,378 +200,524 @@ namespace ignite * * @return Server host. */ - const std::string& GetHost() const; + const std::string& GetHostname() const; /** * Set server host. * * @param server Server host. */ - void SetHost(const std::string& server); + void SetHostname(const std::string& host); /** * Check if the value set. * * @return @true if the value set. */ - bool IsHostSet() const; + bool IsHostnameSet() const; + + /** + * Get server port. + * + * @return Server port. + */ + uint16_t GetTcpPort() const; + + /** + * Set server port. + * + * @param port Server port. + */ + void SetTcpPort(uint16_t port); + + /** + * Check if the value set. + * + * @return @true if the value set. + */ + bool IsTcpPortSet() const; /** * Get schema. * * @return Schema. */ - const std::string& GetSchema() const; + const std::string& GetDatabase() const; /** * Set schema. * * @param schema Schema name. */ - void SetSchema(const std::string& schema); + void SetDatabase(const std::string& schema); /** * Check if the value set. * * @return @true if the value set. */ - bool IsSchemaSet() const; + bool IsDatabaseSet() const; /** - * Get addresses. + * Get user. * - * @return Addresses. + * @return User. */ - const std::vector& GetAddresses() const; + const std::string& GetUser() const; /** - * Set addresses to connect to. + * Set user. * - * @param endPoints Addresses. + * @param user User. */ - void SetAddresses(const std::vector& endPoints); + void SetUser(const std::string& user); /** * Check if the value set. * * @return @true if the value set. */ - bool IsAddressesSet() const; + bool IsUserSet() const; /** - * Get SSL mode. + * Get password. * - * @return SSL mode. + * @return Password. */ - ssl::SslMode::Type GetSslMode() const; + const std::string& GetPassword() const; /** - * Set SSL mode. + * Set password. * - * @param sslMode SSL mode. + * @param pass Password. */ - void SetSslMode(ssl::SslMode::Type sslMode); + void SetPassword(const std::string& pass); /** * Check if the value set. * * @return @true if the value set. */ - bool IsSslModeSet() const; + bool IsPasswordSet() const; + + /** + * Get password. + * + * @return Password. + */ + const std::string& GetApplicationName() const; + + /** + * Set password. + * + * @param pass Password. + */ + void SetApplicationName(const std::string& name); + + /** + * Check if the value set. + * + * @return @true if the value set. + */ + bool IsApplicationNameSet() const; + + /** + * Get fetch results page size. + * + * @return Fetch results page size. + */ + int32_t GetLoginTimeoutSeconds() const; + + /** + * Set fetch results page size. + * + * @param size Fetch results page size. + */ + void SetLoginTimeoutSeconds(int32_t seconds); + + /** + * Check if the value set. + * + * @return @true if the value set. + */ + bool IsLoginTimeoutSecondsSet() const; + + /** + * Get password. + * + * @return Password. + */ + const std::string& GetReadPreference() const; /** - * Get SSL key file path. + * Set password. + * + * @param pass Password. + */ + void SetReadPreference(const std::string& preference); + + /** + * Check if the value set. + * + * @return @true if the value set. + */ + bool IsReadPreferenceSet() const; + /** + * Get password. * - * @return SSL key file path. + * @return Password. */ - const std::string& GetSslKeyFile() const; + const std::string& GetReplicaSet() const; /** - * Set SSL key file path. + * Set password. * - * @param sslKeyFile SSL key file path. + * @param pass Password. */ - void SetSslKeyFile(const std::string& sslKeyFile); + void SetReplicaSet(const std::string& name); /** * Check if the value set. * * @return @true if the value set. */ - bool IsSslKeyFileSet() const; + bool IsReplicaSetSet() const; /** - * Get SSL certificate file path. + * Get password. * - * @return SSL certificate file path. + * @return Password. */ - const std::string& GetSslCertFile() const; + bool IsRetryReads() const; /** - * Set SSL certificate file path. + * Set password. * - * @param sslCertFile SSL certificate file path. + * @param pass Password. */ - void SetSslCertFile(const std::string& sslCertFile); + void SetRetryReads(bool val); /** * Check if the value set. * * @return @true if the value set. */ - bool IsSslCertFileSet() const; + bool IsRetryReadsSet() const; /** - * Get SSL certificate authority file path. + * Get password. * - * @return SSL certificate authority file path. + * @return Password. */ - const std::string& GetSslCaFile() const; + bool IsTls() const; /** - * Set SSL certificate authority file path. + * Set password. * - * @param sslCaFile SSL certificate authority file path. + * @param pass Password. */ - void SetSslCaFile(const std::string& sslCaFile); + void SetTls(bool val); /** * Check if the value set. * * @return @true if the value set. */ - bool IsSslCaFileSet() const; + bool IsTlsSet() const; + + /** + * Get password. + * + * @return Password. + */ + bool IsTlsAllowInvalidHostnames() const; + + /** + * Set password. + * + * @param pass Password. + */ + void SetTlsAllowInvalidHostnames(bool val); /** - * Check distributed joins flag. + * Check if the value set. * - * @return True if distributed joins are enabled. + * @return @true if the value set. */ - bool IsDistributedJoins() const; + bool IsTlsAllowInvalidHostnamesSet() const; + + /** + * Get password. + * + * @return Password. + */ + const std::string& GetTlsCaFile() const; /** - * Set distributed joins. + * Set password. * - * @param val Value to set. + * @param pass Password. */ - void SetDistributedJoins(bool val); + void SetTlsCaFile(const std::string& path); /** * Check if the value set. * * @return @true if the value set. */ - bool IsDistributedJoinsSet() const; + bool IsTlsCaFileSet() const; /** - * Check enforce join order flag. + * Get password. * - * @return True if enforcing of join order is enabled. + * @return Password. */ - bool IsEnforceJoinOrder() const; + const std::string& GetSshUser() const; /** - * Set enforce joins. + * Set password. * - * @param val Value to set. + * @param pass Password. */ - void SetEnforceJoinOrder(bool val); + void SetSshUser(const std::string& user); /** * Check if the value set. * * @return @true if the value set. */ - bool IsEnforceJoinOrderSet() const; + bool IsSshUserSet() const; /** - * Check replicated only flag. + * Get password. * - * @return True if replicated only is enabled. + * @return Password. */ - bool IsReplicatedOnly() const; + const std::string& GetSshHost() const; /** - * Set replicated only flag. + * Set password. * - * @param val Value to set. + * @param pass Password. */ - void SetReplicatedOnly(bool val); + void SetSshHost(const std::string& host); /** * Check if the value set. * * @return @true if the value set. */ - bool IsReplicatedOnlySet() const; + bool IsSshHostSet() const; /** - * Check collocated flag. + * Get password. * - * @return True if collocated is enabled. + * @return Password. */ - bool IsCollocated() const; + const std::string& GetSshPrivateKeyFile () const; /** - * Set collocated. + * Set password. * - * @param val Value to set. + * @param pass Password. */ - void SetCollocated(bool val); + void SetSshPrivateKeyFile(const std::string& path); /** * Check if the value set. * * @return @true if the value set. */ - bool IsCollocatedSet() const; + bool IsSshPrivateKeyFileSet() const; /** - * Check lazy flag. + * Get password. * - * @return True if lazy is enabled. + * @return Password. */ - bool IsLazy() const; + const std::string& GetSshPrivateKeyPassphrase() const; /** - * Set lazy. + * Set password. * - * @param val Value to set. + * @param pass Password. */ - void SetLazy(bool val); + void SetSshPrivateKeyPassphrase(const std::string& passphrase); /** * Check if the value set. * * @return @true if the value set. */ - bool IsLazySet() const; + bool IsSshPrivateKeyPassphraseSet() const; /** - * Check update on server flag. + * Get password. * - * @return True if update on server. + * @return Password. */ - bool IsSkipReducerOnUpdate() const; + bool IsSshStrictHostKeyChecking() const; /** - * Set update on server. + * Set password. * - * @param val Value to set. + * @param pass Password. */ - void SetSkipReducerOnUpdate(bool val); + void SetSshStrictHostKeyChecking(bool val); /** * Check if the value set. * * @return @true if the value set. */ - bool IsSkipReducerOnUpdateSet() const; + bool IsSshStrictHostKeyCheckingSet() const; /** - * Get protocol version. + * Get password. * - * @return Protocol version. + * @return Password. */ - ProtocolVersion GetProtocolVersion() const; + const std::string& GetSshKnownHostsFile() const; /** - * Set protocol version. + * Set password. * - * @param version Version to set. + * @param pass Password. */ - void SetProtocolVersion(const ProtocolVersion& version); + void SetSshKnownHostsFile(const std::string& path); /** * Check if the value set. * * @return @true if the value set. */ - bool IsProtocolVersionSet() const; + bool IsSshKnownHostsFileSet() const; + + /** + * Get password. + * + * @return Password. + */ + const std::string& GetScanMethod() const; + + /** + * Set password. + * + * @param pass Password. + */ + void SetScanMethod(const std::string& method); + + /** + * Check if the value set. + * + * @return @true if the value set. + */ + bool IsScanMethodSet() const; /** * Get fetch results page size. * * @return Fetch results page size. */ - int32_t GetPageSize() const; + int32_t GetScanLimit() const; /** * Set fetch results page size. * * @param size Fetch results page size. */ - void SetPageSize(int32_t size); + void SetScanLimit(int32_t limit); /** * Check if the value set. * * @return @true if the value set. */ - bool IsPageSizeSet() const; + bool IsScanLimitSet() const; /** - * Get user. - * - * @return User. - */ - const std::string& GetUser() const; + * Get password. + * + * @return Password. + */ + const std::string& GetSchemaName() const; /** - * Set user. + * Set password. * - * @param user User. + * @param pass Password. */ - void SetUser(const std::string& user); + void SetSchemaName(const std::string& method); /** * Check if the value set. * * @return @true if the value set. */ - bool IsUserSet() const; + bool IsSchemaNameSet() const; /** * Get password. * * @return Password. */ - const std::string& GetPassword() const; + bool IsSchemaRefresh() const; /** * Set password. * * @param pass Password. */ - void SetPassword(const std::string& pass); + void SetSchemaRefresh(bool val); /** * Check if the value set. * * @return @true if the value set. */ - bool IsPasswordSet() const; + bool IsSchemaRefreshSet() const; /** - * Get nested transaction mode. + * Get addresses. * - * @return Nested transaction mode. + * @return Addresses. */ - NestedTxMode::Type GetNestedTxMode() const; + const std::vector& GetAddresses() const; /** - * Set nested transaction mode. + * Set addresses to connect to. * - * @param mode Nested transaction mode. + * @param endPoints Addresses. */ - void SetNestedTxMode(NestedTxMode::Type mode); + void SetAddresses(const std::vector& endPoints); /** * Check if the value set. * * @return @true if the value set. */ - bool IsNestedTxModeSet() const; + bool IsAddressesSet() const; + + /** + * Get fetch results page size. + * + * @return Fetch results page size. + */ + int32_t GetDefaultFetchSize() const; + + /** + * Set fetch results page size. + * + * @param size Fetch results page size. + */ + void SetDefaultFetchSize(int32_t size); + + /** + * Check if the value set. + * + * @return @true if the value set. + */ + bool IsDefaultFetchSizeSet() const; /** * Get argument map. @@ -586,61 +744,79 @@ namespace ignite SettableValue driver; /** Schema. */ - SettableValue schema; + SettableValue database; /** Server. Deprecated. */ - SettableValue server; + SettableValue hostname; /** TCP port. Deprecated. */ SettableValue port; - /** Request and response page size. */ - SettableValue pageSize; - - /** Distributed joins flag. */ - SettableValue distributedJoins; + /** User. */ + SettableValue user; - /** Enforce join order flag. */ - SettableValue enforceJoinOrder; + /** Password. */ + SettableValue password; - /** Replicated only flag. */ - SettableValue replicatedOnly; + /** Application name. */ + SettableValue appName; - /** Collocated flag. */ - SettableValue collocated; + /** Login timeout in seconds. */ + SettableValue loginTimeoutSec; - /** Lazy flag. */ - SettableValue lazy; + /** Read pereference. */ + SettableValue readPreference; - /** Skip reducer on update flag. */ - SettableValue skipReducerOnUpdate; + /** Replica set name. */ + SettableValue replicaSet; - /** Protocol version. */ - SettableValue protocolVersion; + /** Retry reads flag. */ + SettableValue retryReads; /** Connection end-points. */ - SettableValue< std::vector > endPoints; + SettableValue< std::vector > endPoints; // Remove in favor of deprecated one - /** SSL Mode. */ - SettableValue sslMode; + /** Enable SSL/TLS. */ + SettableValue tls; - /** SSL private key file path. */ - SettableValue sslKeyFile; + /** Flag for if invalid hostnames for the TLS certificate are allowed. */ + SettableValue tlsAllowInvalidHostnames; - /** SSL certificate file path. */ - SettableValue sslCertFile; + /** SSL/TLS certificate authority file path. */ + SettableValue tlsCaFile; - /** SSL certificate authority file path. */ - SettableValue sslCaFile; + /** The SSH host username for the internal SSH tunnel. */ + SettableValue sshUser; - /** User. */ - SettableValue user; + /** The SSH host host name for the internal SSH tunnel. */ + SettableValue sshHost; - /** Password. */ - SettableValue password; + /** The SSH host private key file path for the internal SSH tunnel. */ + SettableValue sshPrivateKeyFile; - /** Nested transaction mode. */ - SettableValue nestedTxMode; + /** The SSH host private key file passphrase for the internal SSH tunnel. */ + SettableValue sshPrivateKeyPassphrase; + + /** Strict host key checking flag for the internal SSH tunnel. */ + SettableValue sshStrictHostKeyChecking; + + /** The known hosts file path for the internal SSH tunnel. */ + SettableValue sshKnownHostsFile; + + /** Scan method. */ + SettableValue scanMethod; + + /** Scan limit. */ + SettableValue scanLimit; + + /** Schema name. */ + SettableValue schemaName; + + /** Refresh schema flag. */ + SettableValue refreshSchema; + + /** Request and response page size. */ + SettableValue defaultFetchSize; }; template<> diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index de02cb45d..27e4f48d2 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -45,7 +45,7 @@ namespace ignite static const std::string driver; /** Connection attribute keyword for schema attribute. */ - static const std::string schema; + static const std::string database; /** Connection attribute keyword for address attribute. */ static const std::string address; @@ -56,29 +56,71 @@ namespace ignite /** Connection attribute keyword for port attribute. */ static const std::string port; - /** Connection attribute keyword for distributed joins attribute. */ - static const std::string distributedJoins; + /** Connection attribute keyword for username attribute. */ + static const std::string user; - /** Connection attribute keyword for enforce join order attribute. */ - static const std::string enforceJoinOrder; + /** Connection attribute keyword for password attribute. */ + static const std::string password; - /** Connection attribute keyword for protocol version attribute. */ - static const std::string protocolVersion; + /** Connection attribute keyword for username attribute. */ + static const std::string appName; - /** Connection attribute keyword for fetch results page size attribute. */ - static const std::string pageSize; + /** Connection attribute keyword for password attribute. */ + static const std::string loginTimeoutSec; + + /** Connection attribute keyword for username attribute. */ + static const std::string readPreference; + + /** Connection attribute keyword for password attribute. */ + static const std::string replicaSet; + + /** Connection attribute keyword for username attribute. */ + static const std::string retryReads; + + /** Connection attribute keyword for password attribute. */ + static const std::string tls; + + /** Connection attribute keyword for password attribute. */ + static const std::string tlsAllowInvalidHostnames; + + /** Connection attribute keyword for password attribute. */ + static const std::string tlsCaFile; - /** Connection attribute keyword for replicated only attribute. */ - static const std::string replicatedOnly; + /** Connection attribute keyword for password attribute. */ + static const std::string sshUser; + + /** Connection attribute keyword for password attribute. */ + static const std::string sshHost; - /** Connection attribute keyword for collocated attribute. */ - static const std::string collocated; + /** Connection attribute keyword for password attribute. */ + static const std::string sshPrivateKeyFile; + + /** Connection attribute keyword for password attribute. */ + static const std::string sshPrivateKeyPassphrase; - /** Connection attribute keyword for lazy attribute. */ - static const std::string lazy; + /** Connection attribute keyword for password attribute. */ + static const std::string sshStrictHostKeyChecking; + + /** Connection attribute keyword for password attribute. */ + static const std::string sshKnownHostsFile; + + /** Connection attribute keyword for password attribute. */ + static const std::string scanMethod; - /** Connection attribute keyword for skipReducerOnUpdate attribute. */ - static const std::string skipReducerOnUpdate; + /** Connection attribute keyword for password attribute. */ + static const std::string scanLimit; + + /** Connection attribute keyword for password attribute. */ + static const std::string schemaName; + + /** Connection attribute keyword for password attribute. */ + static const std::string refreshSchema; + + /** Connection attribute keyword for protocol version attribute. */ + static const std::string protocolVersion; + + /** Connection attribute keyword for fetch results page size attribute. */ + static const std::string defaultFetchSize; /** Connection attribute keyword for sslMode attribute. */ static const std::string sslMode; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 38496d993..c8832697c 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -34,7 +34,7 @@ namespace ignite namespace ui { DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, config::Configuration& config): - CustomWindow(parent, "IgniteConfigureDsn", "Configure Apache Ignite DSN"), + CustomWindow(parent, "IgniteConfigureDsn", "Configure Amazon DocumentDB DSN Latest"), width(360), height(600), connectionSettingsGroupBox(), @@ -144,7 +144,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - val = config.GetSchema().c_str(); + val = config.GetDatabase().c_str(); schemaLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Schema name:", ChildId::SCHEMA_LABEL); schemaEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SCHEMA_EDIT); @@ -160,7 +160,7 @@ namespace ignite const ProtocolVersion::VersionSet& supported = ProtocolVersion::GetSupported(); - ProtocolVersion version = config.GetProtocolVersion(); + ProtocolVersion version = ProtocolVersion::GetCurrent(); if (!version.IsSupported()) version = ProtocolVersion::GetCurrent(); @@ -228,7 +228,7 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; - SslMode::Type sslMode = config.GetSslMode(); + SslMode::Type sslMode = ssl::SslMode::REQUIRE; std::string sslModeStr = SslMode::ToString(sslMode); const char* val = sslModeStr.c_str(); @@ -245,7 +245,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - val = config.GetSslKeyFile().c_str(); + val = config.GetTlsCaFile().c_str(); sslKeyFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Private Key:", ChildId::SSL_KEY_FILE_LABEL); sslKeyFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, @@ -255,7 +255,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - val = config.GetSslCertFile().c_str(); + val = config.GetTlsCaFile().c_str(); sslCertFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Certificate:", ChildId::SSL_CERT_FILE_LABEL); sslCertFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, @@ -265,7 +265,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - val = config.GetSslCaFile().c_str(); + val = config.GetTlsCaFile().c_str(); sslCaFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSL Certificate Authority:", ChildId::SSL_CA_FILE_LABEL); sslCaFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, @@ -296,14 +296,14 @@ namespace ignite int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; - ProtocolVersion version = config.GetProtocolVersion(); + ProtocolVersion version = ProtocolVersion::GetCurrent(); if (!version.IsSupported()) version = ProtocolVersion::GetCurrent(); int rowPos = posY + 2 * INTERVAL; - std::string tmp = common::LexicalCast(config.GetPageSize()); + std::string tmp = common::LexicalCast(1000); const char* val = tmp.c_str(); pageSizeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Page size:", ChildId::PAGE_SIZE_LABEL); @@ -326,8 +326,8 @@ namespace ignite { nestedTxModeComboBox->AddString(NestedTxMode::ToString(*it)); - if (*it == config.GetNestedTxMode()) - nestedTxModeComboBox->SetSelection(id); + /* if (*it == config.GetNestedTxMode()) + nestedTxModeComboBox->SetSelection(id); */ ++id; } @@ -337,30 +337,30 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; distributedJoinsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Distributed Joins", ChildId::DISTRIBUTED_JOINS_CHECK_BOX, config.IsDistributedJoins()); + "Distributed Joins", ChildId::DISTRIBUTED_JOINS_CHECK_BOX, false); enforceJoinOrderCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, checkBoxSize, ROW_HEIGHT, "Enforce Join Order", - ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX, config.IsEnforceJoinOrder()); + ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX, false); rowPos += ROW_HEIGHT; replicatedOnlyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Replicated Only", ChildId::REPLICATED_ONLY_CHECK_BOX, config.IsReplicatedOnly()); - + "Replicated Only", ChildId::REPLICATED_ONLY_CHECK_BOX, false); + collocatedCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, checkBoxSize, - ROW_HEIGHT, "Collocated", ChildId::COLLOCATED_CHECK_BOX, config.IsCollocated()); + ROW_HEIGHT, "Collocated", ChildId::COLLOCATED_CHECK_BOX, false); rowPos += ROW_HEIGHT; lazyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Lazy", ChildId::LAZY_CHECK_BOX, config.IsLazy()); + "Lazy", ChildId::LAZY_CHECK_BOX, false); lazyCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_1_5); skipReducerOnUpdateCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, checkBoxSize, ROW_HEIGHT, "Skip reducer on update", ChildId::SKIP_REDUCER_ON_UPDATE_CHECK_BOX, - config.IsSkipReducerOnUpdate()); + false); skipReducerOnUpdateCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_3_0); @@ -550,8 +550,8 @@ namespace ignite cfg.SetDsn(dsnStr); cfg.SetAddresses(addresses); - cfg.SetSchema(schemaStr); - cfg.SetProtocolVersion(version); + cfg.SetDatabase(schemaStr); + //cfg.SetProtocolVersion(version); } void DsnConfigurationWindow::RetrieveAuthParameters(config::Configuration& cfg) const @@ -586,10 +586,10 @@ namespace ignite ssl::SslMode::Type sslMode = ssl::SslMode::FromString(sslModeStr, ssl::SslMode::DISABLE); - cfg.SetSslMode(sslMode); - cfg.SetSslKeyFile(sslKeyStr); - cfg.SetSslCertFile(sslCertStr); - cfg.SetSslCaFile(sslCaStr); + //cfg.SetSslMode(sslMode); + //cfg.SetSslKeyFile(sslKeyStr); + //cfg.SetSslCertFile(sslCertStr); + cfg.SetTlsCaFile(sslCaStr); } void DsnConfigurationWindow::RetrieveAdditionalParameters(config::Configuration& cfg) const @@ -601,39 +601,39 @@ namespace ignite int32_t pageSize = common::LexicalCast(pageSizeStr); if (pageSize <= 0) - pageSize = config.GetPageSize(); - + pageSize = config.GetDefaultFetchSize(); + std::string nestedTxModeStr; nestedTxModeComboBox->GetText(nestedTxModeStr); - NestedTxMode::Type mode = NestedTxMode::FromString(nestedTxModeStr, config.GetNestedTxMode()); + //NestedTxMode::Type mode = NestedTxMode::FromString(nestedTxModeStr, config.GetNestedTxMode()); - bool distributedJoins = distributedJoinsCheckBox->IsChecked(); - bool enforceJoinOrder = enforceJoinOrderCheckBox->IsChecked(); - bool replicatedOnly = replicatedOnlyCheckBox->IsChecked(); - bool collocated = collocatedCheckBox->IsChecked(); - bool lazy = lazyCheckBox->IsChecked(); - bool skipReducerOnUpdate = skipReducerOnUpdateCheckBox->IsChecked(); + //bool distributedJoins = distributedJoinsCheckBox->IsChecked(); + //bool enforceJoinOrder = enforceJoinOrderCheckBox->IsChecked(); + //bool replicatedOnly = replicatedOnlyCheckBox->IsChecked(); + //bool collocated = collocatedCheckBox->IsChecked(); + //bool lazy = lazyCheckBox->IsChecked(); + //bool skipReducerOnUpdate = skipReducerOnUpdateCheckBox->IsChecked(); LOG_MSG("Retrieving arguments:"); LOG_MSG("Page size: " << pageSize); - LOG_MSG("Nested TX Mode: " << NestedTxMode::ToString(mode)); - LOG_MSG("Distributed Joins: " << (distributedJoins ? "true" : "false")); - LOG_MSG("Enforce Join Order: " << (enforceJoinOrder ? "true" : "false")); - LOG_MSG("Replicated only: " << (replicatedOnly ? "true" : "false")); - LOG_MSG("Collocated: " << (collocated ? "true" : "false")); - LOG_MSG("Lazy: " << (lazy ? "true" : "false")); - LOG_MSG("Skip reducer on update: " << (skipReducerOnUpdate ? "true" : "false")); - - cfg.SetPageSize(pageSize); - cfg.SetNestedTxMode(mode); - cfg.SetDistributedJoins(distributedJoins); - cfg.SetEnforceJoinOrder(enforceJoinOrder); - cfg.SetReplicatedOnly(replicatedOnly); - cfg.SetCollocated(collocated); - cfg.SetLazy(lazy); - cfg.SetSkipReducerOnUpdate(skipReducerOnUpdate); + //LOG_MSG("Nested TX Mode: " << NestedTxMode::ToString(mode)); + //LOG_MSG("Distributed Joins: " << (distributedJoins ? "true" : "false")); + //LOG_MSG("Enforce Join Order: " << (enforceJoinOrder ? "true" : "false")); + //LOG_MSG("Replicated only: " << (replicatedOnly ? "true" : "false")); + //LOG_MSG("Collocated: " << (collocated ? "true" : "false")); + //LOG_MSG("Lazy: " << (lazy ? "true" : "false")); + //LOG_MSG("Skip reducer on update: " << (skipReducerOnUpdate ? "true" : "false")); + + cfg.SetDefaultFetchSize(pageSize); + //cfg.SetNestedTxMode(mode); + //cfg.SetDistributedJoins(distributedJoins); + //cfg.SetEnforceJoinOrder(enforceJoinOrder); + //cfg.SetReplicatedOnly(replicatedOnly); + //cfg.SetCollocated(collocated); + //cfg.SetLazy(lazy); + //cfg.SetSkipReducerOnUpdate(skipReducerOnUpdate); } } } diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index a99894dfc..198ecb9d0 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -30,56 +30,73 @@ namespace ignite { namespace config { + const std::string Configuration::DefaultValue::dsn = "Apache Ignite DSN"; const std::string Configuration::DefaultValue::driver = "Apache Ignite"; - const std::string Configuration::DefaultValue::schema = "PUBLIC"; - const std::string Configuration::DefaultValue::address = ""; - const std::string Configuration::DefaultValue::server = ""; - - const uint16_t Configuration::DefaultValue::port = 10800; - const int32_t Configuration::DefaultValue::pageSize = 1024; - - const bool Configuration::DefaultValue::distributedJoins = false; - const bool Configuration::DefaultValue::enforceJoinOrder = false; - const bool Configuration::DefaultValue::replicatedOnly = false; - const bool Configuration::DefaultValue::collocated = false; - const bool Configuration::DefaultValue::lazy = false; - const bool Configuration::DefaultValue::skipReducerOnUpdate = false; - - const ProtocolVersion& Configuration::DefaultValue::protocolVersion = ProtocolVersion::GetCurrent(); - - const ssl::SslMode::Type Configuration::DefaultValue::sslMode = ssl::SslMode::DISABLE; - const std::string Configuration::DefaultValue::sslKeyFile = ""; - const std::string Configuration::DefaultValue::sslCertFile = ""; - const std::string Configuration::DefaultValue::sslCaFile = ""; - + const std::string Configuration::DefaultValue::database = ""; + const std::string Configuration::DefaultValue::address = ""; // remove + const std::string Configuration::DefaultValue::hostname = ""; + const uint16_t Configuration::DefaultValue::port = 27017; const std::string Configuration::DefaultValue::user = ""; const std::string Configuration::DefaultValue::password = ""; - - const NestedTxMode::Type Configuration::DefaultValue::nestedTxMode = NestedTxMode::AI_ERROR; + + // SSL/TLS options + const bool Configuration::DefaultValue::tls = true; + const bool Configuration::DefaultValue::tlsAllowInvalidHostnames = false; + const std::string Configuration::DefaultValue::tlsCaFile = ""; + + // Schema Generation and Discovery options + const std::string Configuration::DefaultValue::scanMethod = "random"; + const int32_t Configuration::DefaultValue::scanLimit = 1000; + const std::string Configuration::DefaultValue::schemaName = "_default"; + const bool Configuration::DefaultValue::refreshSchema = false; + + // Internal SSH Tunnel options + const std::string Configuration::DefaultValue::sshUser = ""; + const std::string Configuration::DefaultValue::sshHost = ""; + const std::string Configuration::DefaultValue::sshPrivateKeyFile = ""; + const std::string Configuration::DefaultValue::sshPrivateKeyPassphrase = ""; + const bool Configuration::DefaultValue::sshStrictHostKeyChecking = true; + const std::string Configuration::DefaultValue::sshKnownHostsFile = ""; + + // Additional options + const std::string Configuration::DefaultValue::appName = "Amazon DocumentDB ODBC Driver"; + const int32_t Configuration::DefaultValue::loginTimeoutSec = 0; + const std::string Configuration::DefaultValue::readPreference = ""; + const std::string Configuration::DefaultValue::replicaSet = ""; + const bool Configuration::DefaultValue::retryReads = true; + const int32_t Configuration::DefaultValue::defaultFetchSize = 2000; + + const NestedTxMode::Type Configuration::DefaultValue::nestedTxMode = NestedTxMode::AI_ERROR; // remove Configuration::Configuration() : dsn(DefaultValue::dsn), driver(DefaultValue::driver), - schema(DefaultValue::schema), - server(DefaultValue::server), + database(DefaultValue::database), + hostname(DefaultValue::hostname), port(DefaultValue::port), - pageSize(DefaultValue::pageSize), - distributedJoins(DefaultValue::distributedJoins), - enforceJoinOrder(DefaultValue::enforceJoinOrder), - replicatedOnly(DefaultValue::replicatedOnly), - collocated(DefaultValue::collocated), - lazy(DefaultValue::lazy), - skipReducerOnUpdate(DefaultValue::skipReducerOnUpdate), - protocolVersion(DefaultValue::protocolVersion), - endPoints(std::vector()), - sslMode(DefaultValue::sslMode), - sslKeyFile(DefaultValue::sslKeyFile), - sslCertFile(DefaultValue::sslCertFile), - sslCaFile(DefaultValue::sslCaFile), user(DefaultValue::user), password(DefaultValue::password), - nestedTxMode(DefaultValue::nestedTxMode) + endPoints(std::vector()), + appName(DefaultValue::appName), + loginTimeoutSec(DefaultValue::loginTimeoutSec), + readPreference(DefaultValue::readPreference), + replicaSet(DefaultValue::replicaSet), + retryReads(DefaultValue::retryReads), + tls(DefaultValue::tls), + tlsAllowInvalidHostnames(DefaultValue::tlsAllowInvalidHostnames), + tlsCaFile(DefaultValue::tlsCaFile), + sshUser(DefaultValue::sshUser), + sshHost(DefaultValue::sshHost), + sshPrivateKeyFile(DefaultValue::sshPrivateKeyFile), + sshPrivateKeyPassphrase(DefaultValue::sshPrivateKeyPassphrase), + sshStrictHostKeyChecking(DefaultValue::sshStrictHostKeyChecking), + sshKnownHostsFile(DefaultValue::sshKnownHostsFile), + scanMethod(DefaultValue::scanMethod), + scanLimit(DefaultValue::scanLimit), + schemaName(DefaultValue::schemaName), + refreshSchema(DefaultValue::refreshSchema), + defaultFetchSize(DefaultValue::defaultFetchSize) { // No-op. } @@ -157,34 +174,34 @@ namespace ignite this->driver.SetValue(driver); } - const std::string& Configuration::GetHost() const + const std::string& Configuration::GetHostname() const { - return server.GetValue(); + return hostname.GetValue(); } - void Configuration::SetHost(const std::string& server) + void Configuration::SetHostname(const std::string& host) { - this->server.SetValue(server); + this->hostname.SetValue(host); } - bool Configuration::IsHostSet() const + bool Configuration::IsHostnameSet() const { - return server.IsSet(); + return hostname.IsSet(); } - const std::string& Configuration::GetSchema() const + const std::string& Configuration::GetDatabase() const { - return schema.GetValue(); + return database.GetValue(); } - void Configuration::SetSchema(const std::string& schema) + void Configuration::SetDatabase(const std::string& schema) { - this->schema.SetValue(schema); + this->database.SetValue(schema); } - bool Configuration::IsSchemaSet() const + bool Configuration::IsDatabaseSet() const { - return schema.IsSet(); + return database.IsSet(); } const std::vector& Configuration::GetAddresses() const @@ -202,179 +219,274 @@ namespace ignite return endPoints.IsSet(); } - ssl::SslMode::Type Configuration::GetSslMode() const + const std::string& Configuration::GetApplicationName() const + { + return appName.GetValue(); + } + + void Configuration::SetApplicationName(const std::string& name) + { + this->appName.SetValue(name); + } + + bool Configuration::IsApplicationNameSet() const + { + return appName.IsSet(); + } + + int32_t Configuration::GetLoginTimeoutSeconds() const { - return sslMode.GetValue(); + return loginTimeoutSec.GetValue(); } - void Configuration::SetSslMode(ssl::SslMode::Type sslMode) + void Configuration::SetLoginTimeoutSeconds(int32_t seconds) { - this->sslMode.SetValue(sslMode); + this->loginTimeoutSec.SetValue(seconds); } - bool Configuration::IsSslModeSet() const + bool Configuration::IsLoginTimeoutSecondsSet() const { - return sslMode.IsSet(); + return loginTimeoutSec.IsSet(); } - const std::string& Configuration::GetSslKeyFile() const + const std::string& Configuration::GetReadPreference() const { - return sslKeyFile.GetValue(); + return readPreference.GetValue(); } - void Configuration::SetSslKeyFile(const std::string& sslKeyFile) + void Configuration::SetReadPreference(const std::string& preference) { - this->sslKeyFile.SetValue(sslKeyFile); + this->readPreference.SetValue(preference); } - bool Configuration::IsSslKeyFileSet() const + bool Configuration::IsReadPreferenceSet() const { - return sslKeyFile.IsSet(); + return readPreference.IsSet(); } - const std::string& Configuration::GetSslCertFile() const + const std::string& Configuration::GetReplicaSet() const { - return sslCertFile.GetValue(); + return replicaSet.GetValue(); } - void Configuration::SetSslCertFile(const std::string& sslCertFile) + void Configuration::SetReplicaSet(const std::string& name) { - this->sslCertFile.SetValue(sslCertFile); + this->replicaSet.SetValue(name); } - bool Configuration::IsSslCertFileSet() const + bool Configuration::IsReplicaSetSet() const { - return sslCertFile.IsSet(); + return replicaSet.IsSet(); } - const std::string& Configuration::GetSslCaFile() const + bool Configuration::IsRetryReads() const { - return sslCaFile.GetValue(); + return retryReads.GetValue(); } - void Configuration::SetSslCaFile(const std::string& sslCaFile) + void Configuration::SetRetryReads(bool val) { - this->sslCaFile.SetValue(sslCaFile); + this->retryReads.SetValue(val); } - bool Configuration::IsSslCaFileSet() const + bool Configuration::IsRetryReadsSet() const { - return sslCaFile.IsSet(); + return retryReads.IsSet(); } - bool Configuration::IsDistributedJoins() const + bool Configuration::IsTls() const { - return distributedJoins.GetValue(); + return tls.GetValue(); } - void Configuration::SetDistributedJoins(bool val) + void Configuration::SetTls(bool val) { - this->distributedJoins.SetValue(val); + this->tls.SetValue(val); } - bool Configuration::IsDistributedJoinsSet() const + bool Configuration::IsTlsSet() const { - return distributedJoins.IsSet(); + return tls.IsSet(); } - bool Configuration::IsEnforceJoinOrder() const + bool Configuration::IsTlsAllowInvalidHostnames() const { - return enforceJoinOrder.GetValue(); + return tlsAllowInvalidHostnames.GetValue(); } - void Configuration::SetEnforceJoinOrder(bool val) + void Configuration::SetTlsAllowInvalidHostnames(bool val) { - this->enforceJoinOrder.SetValue(val); + this->tlsAllowInvalidHostnames.SetValue(val); } - bool Configuration::IsEnforceJoinOrderSet() const + bool Configuration::IsTlsAllowInvalidHostnamesSet() const { - return enforceJoinOrder.IsSet(); + return tlsAllowInvalidHostnames.IsSet(); } - bool Configuration::IsReplicatedOnly() const + const std::string& Configuration::GetTlsCaFile() const { - return replicatedOnly.GetValue(); + return tlsCaFile.GetValue(); } - void Configuration::SetReplicatedOnly(bool val) + void Configuration::SetTlsCaFile(const std::string& path) { - this->replicatedOnly.SetValue(val); + this->tlsCaFile.SetValue(path); } - bool Configuration::IsReplicatedOnlySet() const + bool Configuration::IsTlsCaFileSet() const { - return replicatedOnly.IsSet(); + return tlsCaFile.IsSet(); } - bool Configuration::IsCollocated() const + const std::string& Configuration::GetSshUser() const { - return collocated.GetValue(); + return sshUser.GetValue(); } - void Configuration::SetCollocated(bool val) + void Configuration::SetSshUser(const std::string& username) { - this->collocated.SetValue(val); + this->sshUser.SetValue(username); } - bool Configuration::IsCollocatedSet() const + bool Configuration::IsSshUserSet() const { - return collocated.IsSet(); + return sshUser.IsSet(); } - bool Configuration::IsLazy() const + const std::string& Configuration::GetSshHost() const { - return lazy.GetValue(); + return sshHost.GetValue(); } - void Configuration::SetLazy(bool val) + void Configuration::SetSshHost(const std::string& hostname) { - this->lazy.SetValue(val); + this->sshHost.SetValue(hostname); } - bool Configuration::IsLazySet() const + bool Configuration::IsSshHostSet() const { - return lazy.IsSet(); + return sshHost.IsSet(); } - bool Configuration::IsSkipReducerOnUpdate() const + const std::string& Configuration::GetSshPrivateKeyFile() const { - return skipReducerOnUpdate.GetValue(); + return sshPrivateKeyFile.GetValue(); } - void Configuration::SetSkipReducerOnUpdate(bool val) + void Configuration::SetSshPrivateKeyFile(const std::string& path) { - this->skipReducerOnUpdate.SetValue(val); + this->sshPrivateKeyFile.SetValue(path); } - bool Configuration::IsSkipReducerOnUpdateSet() const + bool Configuration::IsSshPrivateKeyFileSet() const { - return skipReducerOnUpdate.IsSet(); + return sshPrivateKeyFile.IsSet(); } - ProtocolVersion Configuration::GetProtocolVersion() const + const std::string& Configuration::GetSshPrivateKeyPassphrase() const { - return protocolVersion.GetValue(); + return sshPrivateKeyPassphrase.GetValue(); } - void Configuration::SetProtocolVersion(const ProtocolVersion& version) + void Configuration::SetSshPrivateKeyPassphrase(const std::string& passphrase) { - this->protocolVersion.SetValue(version); + this->sshPrivateKeyPassphrase.SetValue(passphrase); } - bool Configuration::IsProtocolVersionSet() const + bool Configuration::IsSshPrivateKeyPassphraseSet() const { - return protocolVersion.IsSet(); + return sshPrivateKeyPassphrase.IsSet(); } - void Configuration::SetPageSize(int32_t size) + bool Configuration::IsSshStrictHostKeyChecking() const { - this->pageSize.SetValue(size); + return sshStrictHostKeyChecking.GetValue(); } - bool Configuration::IsPageSizeSet() const + void Configuration::SetSshStrictHostKeyChecking(bool val) { - return pageSize.IsSet(); + this->sshStrictHostKeyChecking.SetValue(val); + } + + bool Configuration::IsSshStrictHostKeyCheckingSet() const + { + return sshStrictHostKeyChecking.IsSet(); + } + + const std::string& Configuration::GetSshKnownHostsFile() const + { + return sshKnownHostsFile.GetValue(); + } + + void Configuration::SetSshKnownHostsFile(const std::string& path) + { + this->sshKnownHostsFile.SetValue(path); + } + + bool Configuration::IsSshKnownHostsFileSet() const + { + return sshKnownHostsFile.IsSet(); + } + + const std::string& Configuration::GetScanMethod() const + { + return scanMethod.GetValue(); + } + + void Configuration::SetScanMethod(const std::string& method) + { + this->scanMethod.SetValue(method); + } + + bool Configuration::IsScanMethodSet() const + { + return scanMethod.IsSet(); + } + + int32_t Configuration::GetScanLimit() const + { + return scanLimit.GetValue(); + } + + void Configuration::SetScanLimit(int32_t limit) + { + this->scanLimit.SetValue(limit); + } + + bool Configuration::IsScanLimitSet() const + { + return scanLimit.IsSet(); + } + + const std::string& Configuration::GetSchemaName() const + { + return schemaName.GetValue(); + } + + void Configuration::SetSchemaName(const std::string& name) + { + this->schemaName.SetValue(name); + } + + bool Configuration::IsSchemaNameSet() const + { + return schemaName.IsSet(); + } + + bool Configuration::IsSchemaRefresh() const + { + return refreshSchema.GetValue(); + } + + void Configuration::SetSchemaRefresh(bool val) + { + this->refreshSchema.SetValue(val); + } + + bool Configuration::IsSchemaRefreshSet() const + { + return refreshSchema.IsSet(); } const std::string& Configuration::GetUser() const @@ -407,49 +519,51 @@ namespace ignite return password.IsSet(); } - NestedTxMode::Type Configuration::GetNestedTxMode() const - { - return nestedTxMode.GetValue(); - } - - void Configuration::SetNestedTxMode(NestedTxMode::Type mode) + int32_t Configuration::GetDefaultFetchSize() const { - this->nestedTxMode.SetValue(mode); + return defaultFetchSize.GetValue(); } - bool Configuration::IsNestedTxModeSet() const + void Configuration::SetDefaultFetchSize(int32_t size) { - return nestedTxMode.IsSet(); + this->defaultFetchSize.SetValue(size); } - int32_t Configuration::GetPageSize() const + bool Configuration::IsDefaultFetchSizeSet() const { - return pageSize.GetValue(); + return defaultFetchSize.IsSet(); } void Configuration::ToMap(ArgumentMap& res) const { + // Need to add properties here!! AddToMap(res, ConnectionStringParser::Key::dsn, dsn); AddToMap(res, ConnectionStringParser::Key::driver, driver); - AddToMap(res, ConnectionStringParser::Key::schema, schema); + AddToMap(res, ConnectionStringParser::Key::database, database); AddToMap(res, ConnectionStringParser::Key::address, endPoints); - AddToMap(res, ConnectionStringParser::Key::server, server); + AddToMap(res, ConnectionStringParser::Key::server, hostname); AddToMap(res, ConnectionStringParser::Key::port, port); - AddToMap(res, ConnectionStringParser::Key::distributedJoins, distributedJoins); - AddToMap(res, ConnectionStringParser::Key::enforceJoinOrder, enforceJoinOrder); - AddToMap(res, ConnectionStringParser::Key::protocolVersion, protocolVersion); - AddToMap(res, ConnectionStringParser::Key::pageSize, pageSize); - AddToMap(res, ConnectionStringParser::Key::replicatedOnly, replicatedOnly); - AddToMap(res, ConnectionStringParser::Key::collocated, collocated); - AddToMap(res, ConnectionStringParser::Key::lazy, lazy); - AddToMap(res, ConnectionStringParser::Key::skipReducerOnUpdate, skipReducerOnUpdate); - AddToMap(res, ConnectionStringParser::Key::sslMode, sslMode); - AddToMap(res, ConnectionStringParser::Key::sslKeyFile, sslKeyFile); - AddToMap(res, ConnectionStringParser::Key::sslCertFile, sslCertFile); - AddToMap(res, ConnectionStringParser::Key::sslCaFile, sslCaFile); AddToMap(res, ConnectionStringParser::Key::user, user); AddToMap(res, ConnectionStringParser::Key::password, password); - AddToMap(res, ConnectionStringParser::Key::nestedTxMode, nestedTxMode); + AddToMap(res, ConnectionStringParser::Key::appName, appName); + AddToMap(res, ConnectionStringParser::Key::loginTimeoutSec, loginTimeoutSec); + AddToMap(res, ConnectionStringParser::Key::readPreference, readPreference); + AddToMap(res, ConnectionStringParser::Key::replicaSet, replicaSet); + AddToMap(res, ConnectionStringParser::Key::retryReads, retryReads); + AddToMap(res, ConnectionStringParser::Key::tls, tls); + AddToMap(res, ConnectionStringParser::Key::tlsAllowInvalidHostnames, tlsAllowInvalidHostnames); + AddToMap(res, ConnectionStringParser::Key::tlsCaFile, tlsCaFile); + AddToMap(res, ConnectionStringParser::Key::sshUser, sshUser); + AddToMap(res, ConnectionStringParser::Key::sshHost, sshHost); + AddToMap(res, ConnectionStringParser::Key::sshPrivateKeyFile, sshPrivateKeyFile); + AddToMap(res, ConnectionStringParser::Key::sshPrivateKeyPassphrase, sshPrivateKeyPassphrase); + AddToMap(res, ConnectionStringParser::Key::sshStrictHostKeyChecking, sshStrictHostKeyChecking); + AddToMap(res, ConnectionStringParser::Key::sshKnownHostsFile, sshKnownHostsFile); + AddToMap(res, ConnectionStringParser::Key::scanMethod, scanMethod); + AddToMap(res, ConnectionStringParser::Key::scanLimit, scanLimit); + AddToMap(res, ConnectionStringParser::Key::schemaName, schemaName); + AddToMap(res, ConnectionStringParser::Key::refreshSchema, refreshSchema); + AddToMap(res, ConnectionStringParser::Key::defaultFetchSize, defaultFetchSize); } template<> diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index a93e3b575..308bb225b 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -31,29 +31,35 @@ namespace ignite { namespace config { - const std::string ConnectionStringParser::Key::dsn = "dsn"; - const std::string ConnectionStringParser::Key::driver = "driver"; - const std::string ConnectionStringParser::Key::schema = "schema"; - const std::string ConnectionStringParser::Key::address = "address"; - const std::string ConnectionStringParser::Key::server = "server"; - const std::string ConnectionStringParser::Key::port = "port"; - const std::string ConnectionStringParser::Key::distributedJoins = "distributed_joins"; - const std::string ConnectionStringParser::Key::enforceJoinOrder = "enforce_join_order"; - const std::string ConnectionStringParser::Key::protocolVersion = "protocol_version"; - const std::string ConnectionStringParser::Key::pageSize = "page_size"; - const std::string ConnectionStringParser::Key::replicatedOnly = "replicated_only"; - const std::string ConnectionStringParser::Key::collocated = "collocated"; - const std::string ConnectionStringParser::Key::lazy = "lazy"; - const std::string ConnectionStringParser::Key::skipReducerOnUpdate = "skip_reducer_on_update"; - const std::string ConnectionStringParser::Key::sslMode = "ssl_mode"; - const std::string ConnectionStringParser::Key::sslKeyFile = "ssl_key_file"; - const std::string ConnectionStringParser::Key::sslCertFile = "ssl_cert_file"; - const std::string ConnectionStringParser::Key::sslCaFile = "ssl_ca_file"; - const std::string ConnectionStringParser::Key::user = "user"; - const std::string ConnectionStringParser::Key::password = "password"; - const std::string ConnectionStringParser::Key::uid = "uid"; - const std::string ConnectionStringParser::Key::pwd = "pwd"; - const std::string ConnectionStringParser::Key::nestedTxMode = "nested_tx_mode"; + const std::string ConnectionStringParser::Key::dsn = "dsn"; + const std::string ConnectionStringParser::Key::driver = "driver"; + const std::string ConnectionStringParser::Key::database = "database"; + const std::string ConnectionStringParser::Key::address = "address"; + const std::string ConnectionStringParser::Key::server = "server"; + const std::string ConnectionStringParser::Key::port = "port"; + const std::string ConnectionStringParser::Key::user = "user"; + const std::string ConnectionStringParser::Key::password = "password"; + const std::string ConnectionStringParser::Key::appName = "app_name"; + const std::string ConnectionStringParser::Key::loginTimeoutSec = "login_timeout_sec"; + const std::string ConnectionStringParser::Key::readPreference = "read_preference"; + const std::string ConnectionStringParser::Key::replicaSet = "replica_set"; + const std::string ConnectionStringParser::Key::retryReads = "retry_reads"; + const std::string ConnectionStringParser::Key::tls = "tls"; + const std::string ConnectionStringParser::Key::tlsAllowInvalidHostnames = "tls_allow_invalid_hostnames"; + const std::string ConnectionStringParser::Key::tlsCaFile = "tls_ca_file"; + const std::string ConnectionStringParser::Key::sshUser = "ssh_user"; + const std::string ConnectionStringParser::Key::sshHost = "ssh_host"; + const std::string ConnectionStringParser::Key::sshPrivateKeyFile = "ssh_private_key_file"; + const std::string ConnectionStringParser::Key::sshPrivateKeyPassphrase = "ssh_private_key_passphrase"; + const std::string ConnectionStringParser::Key::sshStrictHostKeyChecking = "ssh_strict_host_key_checking"; + const std::string ConnectionStringParser::Key::sshKnownHostsFile = "ssh_known_hosts_file"; + const std::string ConnectionStringParser::Key::scanMethod = "scan_method"; + const std::string ConnectionStringParser::Key::scanLimit = "scan_limit"; + const std::string ConnectionStringParser::Key::schemaName = "schema_name"; + const std::string ConnectionStringParser::Key::refreshSchema = "refresh_schema"; + const std::string ConnectionStringParser::Key::defaultFetchSize = "default_fetch_size"; + const std::string ConnectionStringParser::Key::uid = "uid"; + const std::string ConnectionStringParser::Key::pwd = "pwd"; ConnectionStringParser::ConnectionStringParser(Configuration& cfg): cfg(cfg) @@ -136,14 +142,14 @@ namespace ignite diagnostic::DiagnosticRecordStorage* diag) { std::string lKey = common::ToLower(key); - + if (lKey == Key::dsn) { cfg.SetDsn(value); } - else if (lKey == Key::schema) + else if (lKey == Key::database) { - cfg.SetSchema(value); + cfg.SetDatabase(value); } else if (lKey == Key::address) { @@ -155,7 +161,7 @@ namespace ignite } else if (lKey == Key::server) { - cfg.SetHost(value); + cfg.SetHostname(value); } else if (lKey == Key::port) { @@ -213,24 +219,53 @@ namespace ignite cfg.SetTcpPort(static_cast(numValue)); } - else if (lKey == Key::distributedJoins) + else if (lKey == Key::appName) { - BoolParseResult::Type res = StringToBool(value); + cfg.SetApplicationName(value); + } + else if (lKey == Key::loginTimeoutSec) + { + if (!common::AllDigits(value)) + { + if (diag) + { + diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, + MakeErrorMessage("Login timeout seconds attribute value contains unexpected characters." + " Using default value.", key, value)); + } - if (res == BoolParseResult::AI_UNRECOGNIZED) + return; + } + + int64_t numValue = 0; + std::stringstream conv; + + conv << value; + conv >> numValue; + + if (numValue <= 0 || numValue > 0xFFFFFFFFL) { if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Unrecognized bool value. Using default value.", key, value)); + MakeErrorMessage("Login timeout seconds attribute value is out of range." + " Using default value.", key, value)); } return; } - cfg.SetDistributedJoins(res == BoolParseResult::AI_TRUE); + cfg.SetScanLimit(static_cast(numValue)); + } + else if (lKey == Key::readPreference) + { + cfg.SetReadPreference(value); } - else if (lKey == Key::enforceJoinOrder) + else if (lKey == Key::replicaSet) + { + cfg.SetReplicaSet(value); + } + else if (lKey == Key::tls) { BoolParseResult::Type res = StringToBool(value); @@ -245,53 +280,78 @@ namespace ignite return; } - cfg.SetEnforceJoinOrder(res == BoolParseResult::AI_TRUE); + cfg.SetTls(res == BoolParseResult::AI_TRUE); } - else if (lKey == Key::protocolVersion) + else if (lKey == Key::tlsAllowInvalidHostnames) { - try - { - ProtocolVersion version = ProtocolVersion::FromString(value); + BoolParseResult::Type res = StringToBool(value); - if (!version.IsSupported()) + if (res == BoolParseResult::AI_UNRECOGNIZED) + { + if (diag) { - if (diag) - { - diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - "Specified version is not supported. Default value used."); - } - - return; + diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, + MakeErrorMessage("Unrecognized bool value. Using default value.", key, value)); } - cfg.SetProtocolVersion(version); - } - catch (IgniteError& err) - { - if (diag) - diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, err.GetText()); + return; } + + cfg.SetTlsAllowInvalidHostnames(res == BoolParseResult::AI_TRUE); } - else if (lKey == Key::pageSize) + else if (lKey == Key::tlsCaFile) { - if (!common::AllDigits(value)) + cfg.SetTlsCaFile(value); + } + else if (lKey == Key::sshUser) + { + cfg.SetSshUser(value); + } + else if (lKey == Key::sshHost) + { + cfg.SetSshHost(value); + } + else if (lKey == Key::sshPrivateKeyFile) + { + cfg.SetSshPrivateKeyFile(value); + } + else if (lKey == Key::sshPrivateKeyPassphrase) + { + cfg.SetSshPrivateKeyPassphrase(value); + } + else if (lKey == Key::sshStrictHostKeyChecking) + { + BoolParseResult::Type res = StringToBool(value); + + if (res == BoolParseResult::AI_UNRECOGNIZED) { if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Page size attribute value contains unexpected characters." - " Using default value.", key, value)); + MakeErrorMessage("Unrecognized bool value. Using default value.", key, value)); } return; } - if (value.size() >= sizeof("4294967295")) + cfg.SetSshStrictHostKeyChecking(res == BoolParseResult::AI_TRUE); + } + else if (lKey == Key::sshKnownHostsFile) + { + cfg.SetSshKnownHostsFile(value); + } + else if (lKey == Key::scanMethod) + { + cfg.SetScanMethod(value); + } + else if (lKey == Key::scanLimit) + { + if (!common::AllDigits(value)) { if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Page size attribute value is too large." + MakeErrorMessage("Scan limit attribute value contains unexpected characters." " Using default value.", key, value)); } @@ -309,33 +369,20 @@ namespace ignite if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Page size attribute value is out of range." + MakeErrorMessage("Scan limit attribute value is out of range." " Using default value.", key, value)); } return; } - cfg.SetPageSize(static_cast(numValue)); + cfg.SetScanLimit(static_cast(numValue)); } - else if (lKey == Key::replicatedOnly) + else if (lKey == Key::schemaName) { - BoolParseResult::Type res = StringToBool(value); - - if (res == BoolParseResult::AI_UNRECOGNIZED) - { - if (diag) - { - diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Unrecognized bool value. Using default value.", key, value)); - } - - return; - } - - cfg.SetReplicatedOnly(res == BoolParseResult::AI_TRUE); + cfg.SetSchemaName(value); } - else if (lKey == Key::collocated) + else if (lKey == Key::refreshSchema) { BoolParseResult::Type res = StringToBool(value); @@ -350,70 +397,57 @@ namespace ignite return; } - cfg.SetCollocated(res == BoolParseResult::AI_TRUE); + cfg.SetTls(res == BoolParseResult::AI_TRUE); } - else if (lKey == Key::lazy) + else if (lKey == Key::defaultFetchSize) { - BoolParseResult::Type res = StringToBool(value); - - if (res == BoolParseResult::AI_UNRECOGNIZED) + if (!common::AllDigits(value)) { if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Unrecognized bool value. Defaulting to 'false'.", key, value)); + MakeErrorMessage("Default fetch size attribute value contains unexpected characters." + " Using default value.", key, value)); } return; } - cfg.SetLazy(res == BoolParseResult::AI_TRUE); - } - else if (lKey == Key::skipReducerOnUpdate) - { - BoolParseResult::Type res = StringToBool(value); - - if (res == BoolParseResult::AI_UNRECOGNIZED) + if (value.size() >= sizeof("4294967295")) { if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Unrecognized bool value. Defaulting to 'false'.", key, value)); + MakeErrorMessage("Page size attribute value is too large." + " Using default value.", key, value)); } return; } - cfg.SetSkipReducerOnUpdate(res == BoolParseResult::AI_TRUE); - } - else if (lKey == Key::sslMode) - { - ssl::SslMode::Type mode = ssl::SslMode::FromString(value); + int64_t numValue = 0; + std::stringstream conv; - if (mode == ssl::SslMode::UNKNOWN) + conv << value; + conv >> numValue; + + if (numValue <= 0 || numValue > 0xFFFFFFFFL) { if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - "Specified SSL mode is not supported. Default value used ('disable')."); + MakeErrorMessage("Page size attribute value is out of range." + " Using default value.", key, value)); } return; } - cfg.SetSslMode(mode); - } - else if (lKey == Key::sslKeyFile) - { - cfg.SetSslKeyFile(value); - } - else if (lKey == Key::sslCertFile) - { - cfg.SetSslCertFile(value); - } - else if (lKey == Key::sslCaFile) + cfg.SetDefaultFetchSize(static_cast(numValue)); + } + else if (lKey == Key::tlsCaFile) { - cfg.SetSslCaFile(value); + cfg.SetTlsCaFile(value); } else if (lKey == Key::driver) { @@ -439,23 +473,6 @@ namespace ignite cfg.SetPassword(value); } - else if (lKey == Key::nestedTxMode) - { - NestedTxMode::Type mode = NestedTxMode::FromString(value); - - if (mode == NestedTxMode::AI_UNKNOWN) - { - if (diag) - { - diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - "Specified nested transaction mode is not supported. Default value used ('error')."); - } - - return; - } - - cfg.SetNestedTxMode(mode); - } else if (diag) { std::stringstream stream; diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index c472716d1..c2875fd7e 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -145,7 +145,8 @@ namespace ignite SqlResult::Type Connection::InitSocket() { - ssl::SslMode::Type sslMode = config.GetSslMode(); + // Removed SSL Mode in DSN. Replaced this with REQUIRE for now. + ssl::SslMode::Type sslMode = ssl::SslMode::REQUIRE; if (sslMode == ssl::SslMode::DISABLE) { @@ -167,8 +168,9 @@ namespace ignite return SqlResult::AI_ERROR; } + // Removed SSL key and cert files from DSN. Replaced with empty string for now. socket.reset(network::ssl::MakeSecureSocketClient( - config.GetSslCertFile(), config.GetSslKeyFile(), config.GetSslCaFile())); + "", "", config.GetTlsCaFile())); return SqlResult::AI_SUCCESS; } @@ -186,7 +188,7 @@ namespace ignite return SqlResult::AI_ERROR; } - if (!config.IsHostSet() && config.IsAddressesSet() && config.GetAddresses().empty()) + if (!config.IsHostnameSet() && config.IsAddressesSet() && config.GetAddresses().empty()) { AddStatusRecord("No valid address to connect."); @@ -392,7 +394,7 @@ namespace ignite const std::string& Connection::GetSchema() const { - return config.GetSchema(); + return config.GetDatabase(); } const config::Configuration& Connection::GetConfiguration() const @@ -418,7 +420,7 @@ namespace ignite SqlResult::Type Connection::InternalTransactionCommit() { - std::string schema = config.GetSchema(); + std::string schema = config.GetDatabase(); app::ParameterSet empty; @@ -459,7 +461,7 @@ namespace ignite SqlResult::Type Connection::InternalTransactionRollback() { - std::string schema = config.GetSchema(); + std::string schema = config.GetDatabase(); app::ParameterSet empty; @@ -636,7 +638,7 @@ namespace ignite SqlResult::Type Connection::MakeRequestHandshake() { - ProtocolVersion protocolVersion = config.GetProtocolVersion(); + /* ProtocolVersion protocolVersion = config.GetProtocolVersion(); if (!protocolVersion.IsSupported()) { @@ -653,6 +655,7 @@ namespace ignite return SqlResult::AI_ERROR; } + */ HandshakeRequest req(config); HandshakeResponse rsp; @@ -695,10 +698,12 @@ namespace ignite if (!rsp.GetError().empty()) constructor << "Additional info: " << rsp.GetError() << " "; - constructor << "Current version of the protocol, used by the server node is " + /* constructor + << "Current version of the protocol, used by the server " + "node is " << rsp.GetCurrentVer().ToString() << ", " << "driver protocol version introduced in version " - << protocolVersion.ToString() << "."; + << protocolVersion.ToString() << "."; */ AddStatusRecord(SqlState::S08004_CONNECTION_REJECTED, constructor.str()); @@ -767,8 +772,6 @@ namespace ignite if (!connected) Close(); - else - parser.SetProtocolVersion(config.GetProtocolVersion()); return connected; } @@ -781,7 +784,7 @@ namespace ignite { LOG_MSG("'Address' is not set. Using legacy connection method."); - endPoints.push_back(EndPoint(cfg.GetHost(), cfg.GetTcpPort())); + endPoints.push_back(EndPoint(cfg.GetHostname(), cfg.GetTcpPort())); return; } diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 8f1a6df16..6526a38bd 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -117,104 +117,125 @@ namespace ignite SettableValue server = ReadDsnString(dsn, ConnectionStringParser::Key::server); - if (server.IsSet() && !config.IsHostSet()) - config.SetHost(server.GetValue()); + if (server.IsSet() && !config.IsHostnameSet()) + config.SetHostname(server.GetValue()); SettableValue port = ReadDsnInt(dsn, ConnectionStringParser::Key::port); if (port.IsSet() && !config.IsTcpPortSet()) config.SetTcpPort(static_cast(port.GetValue())); - SettableValue schema = ReadDsnString(dsn, ConnectionStringParser::Key::schema); + SettableValue database = ReadDsnString(dsn, ConnectionStringParser::Key::database); - if (schema.IsSet() && !config.IsSchemaSet()) - config.SetSchema(schema.GetValue()); + if (database.IsSet() && !config.IsDatabaseSet()) + config.SetDatabase(database.GetValue()); - SettableValue distributedJoins = ReadDsnBool(dsn, ConnectionStringParser::Key::distributedJoins); + SettableValue user = ReadDsnString(dsn, ConnectionStringParser::Key::user); - if (distributedJoins.IsSet() && !config.IsDistributedJoinsSet()) - config.SetDistributedJoins(distributedJoins.GetValue()); + if (user.IsSet() && !config.IsUserSet()) + config.SetUser(user.GetValue()); - SettableValue enforceJoinOrder = ReadDsnBool(dsn, ConnectionStringParser::Key::enforceJoinOrder); + SettableValue password = ReadDsnString(dsn, ConnectionStringParser::Key::password); - if (enforceJoinOrder.IsSet() && !config.IsEnforceJoinOrderSet()) - config.SetEnforceJoinOrder(enforceJoinOrder.GetValue()); + if (password.IsSet() && !config.IsPasswordSet()) + config.SetPassword(password.GetValue()); - SettableValue replicatedOnly = ReadDsnBool(dsn, ConnectionStringParser::Key::replicatedOnly); + SettableValue appName = ReadDsnString(dsn, ConnectionStringParser::Key::appName); - if (replicatedOnly.IsSet() && !config.IsReplicatedOnlySet()) - config.SetReplicatedOnly(replicatedOnly.GetValue()); + if (appName.IsSet() && !config.IsApplicationNameSet()) + config.SetApplicationName(appName.GetValue()); - SettableValue collocated = ReadDsnBool(dsn, ConnectionStringParser::Key::collocated); + SettableValue loginTimeoutSec = ReadDsnInt(dsn, ConnectionStringParser::Key::loginTimeoutSec); - if (collocated.IsSet() && !config.IsCollocatedSet()) - config.SetCollocated(collocated.GetValue()); + if (loginTimeoutSec.IsSet() && !config.IsLoginTimeoutSecondsSet()) + config.SetLoginTimeoutSeconds(loginTimeoutSec.GetValue()); - SettableValue lazy = ReadDsnBool(dsn, ConnectionStringParser::Key::lazy); + SettableValue readPreference = ReadDsnString(dsn, ConnectionStringParser::Key::readPreference); - if (lazy.IsSet() && !config.IsLazySet()) - config.SetLazy(lazy.GetValue()); + if (readPreference.IsSet() && !config.IsReadPreferenceSet()) + config.SetReadPreference(readPreference.GetValue()); - SettableValue skipReducerOnUpdate = ReadDsnBool(dsn, ConnectionStringParser::Key::skipReducerOnUpdate); + SettableValue replicaSet = ReadDsnString(dsn, ConnectionStringParser::Key::replicaSet); - if (skipReducerOnUpdate.IsSet() && !config.IsSkipReducerOnUpdateSet()) - config.SetSkipReducerOnUpdate(skipReducerOnUpdate.GetValue()); + if (replicaSet.IsSet() && !config.IsReplicaSetSet()) + config.SetReplicaSet(replicaSet.GetValue()); - SettableValue versionStr = ReadDsnString(dsn, ConnectionStringParser::Key::protocolVersion); + SettableValue retryReads = ReadDsnBool(dsn, ConnectionStringParser::Key::retryReads); - if (versionStr.IsSet() && !config.IsProtocolVersionSet()) - { - ProtocolVersion version = ProtocolVersion::FromString(versionStr.GetValue()); + if (retryReads.IsSet() && !config.IsRetryReadsSet()) + config.SetRetryReads(retryReads.GetValue()); - if (!version.IsSupported()) - version = Configuration::DefaultValue::protocolVersion; + SettableValue tls = ReadDsnBool(dsn, ConnectionStringParser::Key::tls); - config.SetProtocolVersion(version); - } + if (tls.IsSet() && !config.IsTlsSet()) + config.SetTls(tls.GetValue()); - SettableValue pageSize = ReadDsnInt(dsn, ConnectionStringParser::Key::pageSize); + SettableValue tlsAllowInvalidHostnames = ReadDsnBool(dsn, ConnectionStringParser::Key::tlsAllowInvalidHostnames); - if (pageSize.IsSet() && !config.IsPageSizeSet() && pageSize.GetValue() > 0) - config.SetPageSize(pageSize.GetValue()); + if (tlsAllowInvalidHostnames.IsSet() && !config.IsTlsAllowInvalidHostnamesSet()) + config.SetTlsAllowInvalidHostnames(tlsAllowInvalidHostnames.GetValue()); - SettableValue sslModeStr = ReadDsnString(dsn, ConnectionStringParser::Key::sslMode); + SettableValue tlsCaFile = ReadDsnString(dsn, ConnectionStringParser::Key::tlsCaFile); - if (sslModeStr.IsSet() && !config.IsSslModeSet()) - { - ssl::SslMode::Type sslMode = ssl::SslMode::FromString(sslModeStr.GetValue(), ssl::SslMode::DISABLE); + if (tlsCaFile.IsSet() && !config.IsTlsCaFileSet()) + config.SetTlsCaFile(tlsCaFile.GetValue()); - config.SetSslMode(sslMode); - } + SettableValue sshUser = ReadDsnString(dsn, ConnectionStringParser::Key::sshUser); - SettableValue sslKeyFile = ReadDsnString(dsn, ConnectionStringParser::Key::sslKeyFile); + if (sshUser.IsSet() && !config.IsSshUserSet()) + config.SetSshUser(sshUser.GetValue()); - if (sslKeyFile.IsSet() && !config.IsSslKeyFileSet()) - config.SetSslKeyFile(sslKeyFile.GetValue()); + SettableValue sshHost = ReadDsnString(dsn, ConnectionStringParser::Key::sshHost); - SettableValue sslCertFile = ReadDsnString(dsn, ConnectionStringParser::Key::sslCertFile); + if (sshHost.IsSet() && !config.IsSshHostSet()) + config.SetSshHost(sshHost.GetValue()); - if (sslCertFile.IsSet() && !config.IsSslCertFileSet()) - config.SetSslCertFile(sslCertFile.GetValue()); + SettableValue sshPrivateKeyFile = ReadDsnString(dsn, ConnectionStringParser::Key::sshPrivateKeyFile); - SettableValue sslCaFile = ReadDsnString(dsn, ConnectionStringParser::Key::sslCaFile); + if (sshPrivateKeyFile.IsSet() && !config.IsSshPrivateKeyFileSet()) + config.SetSshPrivateKeyFile(sshPrivateKeyFile.GetValue()); - if (sslCaFile.IsSet() && !config.IsSslCaFileSet()) - config.SetSslCaFile(sslCaFile.GetValue()); + SettableValue sshPrivateKeyPassphrase = ReadDsnString(dsn, ConnectionStringParser::Key::sshPrivateKeyPassphrase); - SettableValue user = ReadDsnString(dsn, ConnectionStringParser::Key::user); + if (sshPrivateKeyPassphrase.IsSet() && !config.IsSshPrivateKeyPassphraseSet()) + config.SetSshPrivateKeyPassphrase(sshPrivateKeyPassphrase.GetValue()); + + SettableValue sshStrictHostKeyChecking = ReadDsnBool(dsn, ConnectionStringParser::Key::sshStrictHostKeyChecking); - if (user.IsSet() && !config.IsUserSet()) - config.SetUser(user.GetValue()); + if (sshStrictHostKeyChecking.IsSet() && !config.IsSshStrictHostKeyCheckingSet()) + config.SetSshStrictHostKeyChecking(sshStrictHostKeyChecking.GetValue()); - SettableValue password = ReadDsnString(dsn, ConnectionStringParser::Key::password); + SettableValue sshKnownHostsFile = ReadDsnString(dsn, ConnectionStringParser::Key::sshKnownHostsFile); - if (password.IsSet() && !config.IsPasswordSet()) - config.SetPassword(password.GetValue()); + if (sshKnownHostsFile.IsSet() && !config.IsSshStrictHostKeyCheckingSet()) + config.SetSshStrictHostKeyChecking(sshStrictHostKeyChecking.GetValue()); + + SettableValue scanMethod = ReadDsnString(dsn, ConnectionStringParser::Key::scanMethod); + + if (scanMethod.IsSet() && !config.IsScanMethodSet()) + config.SetScanMethod(scanMethod.GetValue()); + + SettableValue scanLimit = ReadDsnInt(dsn, ConnectionStringParser::Key::scanLimit); + + if (scanLimit.IsSet() && !config.IsScanLimitSet() + && scanLimit.GetValue() > 0) + config.SetDefaultFetchSize(scanLimit.GetValue()); + + SettableValue schemaName = ReadDsnString(dsn, ConnectionStringParser::Key::schemaName); + + if (schemaName.IsSet() && !config.IsSchemaNameSet()) + config.SetSchemaName(schemaName.GetValue()); + + SettableValue refreshSchema = ReadDsnBool(dsn, ConnectionStringParser::Key::refreshSchema); + + if (refreshSchema.IsSet() && !config.IsSchemaRefreshSet()) + config.SetSchemaRefresh(refreshSchema.GetValue()); - SettableValue nestedTxModeStr = ReadDsnString(dsn, ConnectionStringParser::Key::nestedTxMode); + SettableValue defaultFetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::defaultFetchSize); - if (nestedTxModeStr.IsSet() && !config.IsNestedTxModeSet()) - config.SetNestedTxMode(NestedTxMode::FromString(nestedTxModeStr.GetValue(), config.GetNestedTxMode())); + if (defaultFetchSize.IsSet() && !config.IsDefaultFetchSizeSet() + && defaultFetchSize.GetValue() > 0) + config.SetDefaultFetchSize(defaultFetchSize.GetValue()); } } } diff --git a/src/odbc/src/message.cpp b/src/odbc/src/message.cpp index 946529de3..80b809205 100644 --- a/src/odbc/src/message.cpp +++ b/src/odbc/src/message.cpp @@ -62,14 +62,14 @@ namespace ignite { writer.WriteInt8(RequestType::HANDSHAKE); - ProtocolVersion version = config.GetProtocolVersion(); + ProtocolVersion version = ProtocolVersion::GetCurrent(); writer.WriteInt16(version.GetMajor()); writer.WriteInt16(version.GetMinor()); writer.WriteInt16(version.GetMaintenance()); writer.WriteInt8(ClientType::ODBC); - writer.WriteBool(config.IsDistributedJoins()); + /*writer.WriteBool(config.IsDistributedJoins()); writer.WriteBool(config.IsEnforceJoinOrder()); writer.WriteBool(config.IsReplicatedOnly()); writer.WriteBool(config.IsCollocated()); @@ -87,7 +87,7 @@ namespace ignite } if (version >= ProtocolVersion::VERSION_2_7_0) - writer.WriteInt8(config.GetNestedTxMode()); + writer.WriteInt8(config.GetNestedTxMode());*/ } QueryExecuteRequest::QueryExecuteRequest(const std::string& schema, const std::string& sql, diff --git a/src/odbc/src/query/batch_query.cpp b/src/odbc/src/query/batch_query.cpp index 8b26e0d59..7390b4f59 100644 --- a/src/odbc/src/query/batch_query.cpp +++ b/src/odbc/src/query/batch_query.cpp @@ -52,7 +52,7 @@ namespace ignite if (executed) Close(); - int32_t maxPageSize = connection.GetConfiguration().GetPageSize(); + int32_t maxPageSize = connection.GetConfiguration().GetDefaultFetchSize(); int32_t rowNum = params.GetParamSetSize(); SqlResult::Type res; diff --git a/src/odbc/src/query/data_query.cpp b/src/odbc/src/query/data_query.cpp index 54723a109..d5c4d6a6d 100644 --- a/src/odbc/src/query/data_query.cpp +++ b/src/odbc/src/query/data_query.cpp @@ -193,7 +193,7 @@ namespace ignite if (affected >= 0) return affected; - return connection.GetConfiguration().GetPageSize(); + return connection.GetConfiguration().GetDefaultFetchSize(); } SqlResult::Type DataQuery::NextResultSet() @@ -320,7 +320,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetPageSize()); + QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); QueryFetchResponse rsp(*resultPage); try @@ -361,7 +361,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetPageSize()); + QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); QueryMoreResultsResponse rsp(*resultPage); try From 5914412c6a7d3183bd78d4f1816ad3fa79057f7b Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 18 Jan 2022 14:51:19 -0800 Subject: [PATCH 009/165] remove SSL settings and add TLS checkbox on the Configuration Window --- .../odbc/system/ui/dsn_configuration_window.h | 4 + .../system/ui/dsn_configuration_window.cpp | 104 ++++++++++-------- 2 files changed, 65 insertions(+), 43 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 77974ade3..d528317d3 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -63,6 +63,7 @@ namespace ignite PROTOCOL_VERSION_COMBO_BOX, NESTED_TX_MODE_LABEL, NESTED_TX_MODE_COMBO_BOX, + TLS_CHECK_BOX, SSL_MODE_LABEL, SSL_MODE_COMBO_BOX, SSL_KEY_FILE_LABEL, @@ -278,6 +279,9 @@ namespace ignite /** Cancel button. */ std::auto_ptr cancelButton; + /** TLS Encryption CheckBox. */ + std::auto_ptr< Window > tlsCheckBox; + /** SSL Mode label. */ std::auto_ptr sslModeLabel; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index c8832697c..6f2eab8c4 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -32,15 +32,16 @@ namespace ignite namespace system { namespace ui - { + { // -AL- the constructor. No-op means no operation I think? DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, config::Configuration& config): CustomWindow(parent, "IgniteConfigureDsn", "Configure Amazon DocumentDB DSN Latest"), width(360), height(600), connectionSettingsGroupBox(), - sslSettingsGroupBox(), + sslSettingsGroupBox(), // has a create... function defined + tlsCheckBox(), authSettingsGroupBox(), - additionalSettingsGroupBox(), + // additionalSettingsGroupBox(), nameLabel(), nameEdit(), addressLabel(), @@ -52,7 +53,8 @@ namespace ignite distributedJoinsCheckBox(), enforceJoinOrderCheckBox(), replicatedOnlyCheckBox(), - collocatedCheckBox(), + // collocatedCheckBox(), // -AL- after commenting this out, the checkbox is intact? + // checkbox is created in function DsnConfigurationWindow::CreateAdditionalSettingsGroup protocolVersionLabel(), protocolVersionComboBox(), userLabel(), @@ -98,7 +100,7 @@ namespace ignite throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, buf.str().c_str()); } } - + // the function that actually creates the UI -AL- void DsnConfigurationWindow::OnCreate() { int groupPosY = MARGIN; @@ -108,6 +110,8 @@ namespace ignite groupPosY += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosY, groupSizeY); groupPosY += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosY, groupSizeY); groupPosY += INTERVAL + CreateAdditionalSettingsGroup(MARGIN, groupPosY, groupSizeY); + // test: if above code is commented out, additional settings shouldn't appear in config window. Result: Yes test success. + // what happens here is the height of each subgroup is calculated and appended to the y position of the buttons int cancelPosX = width - MARGIN - BUTTON_WIDTH; int okPosX = cancelPosX - INTERVAL - BUTTON_WIDTH; @@ -216,7 +220,7 @@ namespace ignite } int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) - { + { // TODO: rename function name from Ssl to TLS after UI works using ssl::SslMode; enum { LABEL_WIDTH = 120 }; @@ -228,59 +232,66 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; - SslMode::Type sslMode = ssl::SslMode::REQUIRE; - std::string sslModeStr = SslMode::ToString(sslMode); + int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; - const char* val = sslModeStr.c_str(); + tlsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, + "TLS", ChildId::DISTRIBUTED_JOINS_CHECK_BOX, true); - sslModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSL Mode:", ChildId::SSL_MODE_LABEL); - sslModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, - "", ChildId::SSL_MODE_COMBO_BOX); + rowPos += INTERVAL + ROW_HEIGHT; - sslModeComboBox->AddString("disable"); - sslModeComboBox->AddString("require"); + //SslMode::Type sslMode = ssl::SslMode::REQUIRE; + //std::string sslModeStr = SslMode::ToString(sslMode); - sslModeComboBox->SetSelection(sslMode); + //const char* val = sslModeStr.c_str(); - rowPos += INTERVAL + ROW_HEIGHT; + //sslModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + // "SSL Mode:", ChildId::SSL_MODE_LABEL); + //sslModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, + // "", ChildId::SSL_MODE_COMBO_BOX); - val = config.GetTlsCaFile().c_str(); - sslKeyFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSL Private Key:", ChildId::SSL_KEY_FILE_LABEL); - sslKeyFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, - val, ChildId::SSL_KEY_FILE_EDIT); + //sslModeComboBox->AddString("disable"); + //sslModeComboBox->AddString("require"); - SHAutoComplete(sslKeyFileEdit->GetHandle(), SHACF_DEFAULT); + //sslModeComboBox->SetSelection(sslMode); // set default value to require -AL- - rowPos += INTERVAL + ROW_HEIGHT; + //rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight I believe - val = config.GetTlsCaFile().c_str(); - sslCertFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSL Certificate:", ChildId::SSL_CERT_FILE_LABEL); - sslCertFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, - val, ChildId::SSL_CERT_FILE_EDIT); + //val = config.GetTlsCaFile().c_str(); + //sslKeyFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + // "SSL Private Key:", ChildId::SSL_KEY_FILE_LABEL); + //sslKeyFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, + // val, ChildId::SSL_KEY_FILE_EDIT); - SHAutoComplete(sslCertFileEdit->GetHandle(), SHACF_DEFAULT); + //SHAutoComplete(sslKeyFileEdit->GetHandle(), SHACF_DEFAULT); - rowPos += INTERVAL + ROW_HEIGHT; + //rowPos += INTERVAL + ROW_HEIGHT; - val = config.GetTlsCaFile().c_str(); - sslCaFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSL Certificate Authority:", ChildId::SSL_CA_FILE_LABEL); - sslCaFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, - val, ChildId::SSL_CA_FILE_EDIT); + //val = config.GetTlsCaFile().c_str(); + //sslCertFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + // "SSL Certificate:", ChildId::SSL_CERT_FILE_LABEL); + //sslCertFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, + // val, ChildId::SSL_CERT_FILE_EDIT); - SHAutoComplete(sslCaFileEdit->GetHandle(), SHACF_DEFAULT); + //SHAutoComplete(sslCertFileEdit->GetHandle(), SHACF_DEFAULT); - rowPos += INTERVAL + ROW_HEIGHT; + // rowPos += INTERVAL + ROW_HEIGHT; + + //val = config.GetTlsCaFile().c_str(); + //sslCaFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + // "SSL Certificate Authority:", ChildId::SSL_CA_FILE_LABEL); + //sslCaFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, + // val, ChildId::SSL_CA_FILE_EDIT); + + //SHAutoComplete(sslCaFileEdit->GetHandle(), SHACF_DEFAULT); + + // rowPos += INTERVAL + ROW_HEIGHT; sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); - sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - sslCaFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + //sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + //sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + //sslCaFileEdit->SetEnabled(sslMode != SslMode::DISABLE); return rowPos - posY; } @@ -371,7 +382,7 @@ namespace ignite return rowPos - posY; } - + // -AL- I'm not changing this one yet. bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) @@ -461,7 +472,13 @@ namespace ignite break; } - case ChildId::SSL_MODE_COMBO_BOX: + case ChildId::TLS_CHECK_BOX: { + tlsCheckBox->SetChecked(!tlsCheckBox->IsChecked()); + + break; + } + + case ChildId::SSL_MODE_COMBO_BOX: //-AL- may need to remove this later { using ssl::SslMode; @@ -607,6 +624,7 @@ namespace ignite nestedTxModeComboBox->GetText(nestedTxModeStr); + // unnecessary code is commented out -AL- //NestedTxMode::Type mode = NestedTxMode::FromString(nestedTxModeStr, config.GetNestedTxMode()); //bool distributedJoins = distributedJoinsCheckBox->IsChecked(); From df38b8c7815cb9ae33b460137101ffe7544f38f8 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 18 Jan 2022 14:52:14 -0800 Subject: [PATCH 010/165] add comments for my own work added some comments for my own convenience. Will remove later --- src/odbc/src/config/configuration.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 198ecb9d0..e852bb652 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -14,7 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +// configures for what is defined in .h .h has a lot of setable values, replaces with DocumentDB properties. #include #include #include @@ -33,25 +33,25 @@ namespace ignite const std::string Configuration::DefaultValue::dsn = "Apache Ignite DSN"; const std::string Configuration::DefaultValue::driver = "Apache Ignite"; - const std::string Configuration::DefaultValue::database = ""; + const std::string Configuration::DefaultValue::database = ""; // renamed from Schema const std::string Configuration::DefaultValue::address = ""; // remove const std::string Configuration::DefaultValue::hostname = ""; const uint16_t Configuration::DefaultValue::port = 27017; const std::string Configuration::DefaultValue::user = ""; const std::string Configuration::DefaultValue::password = ""; - // SSL/TLS options - const bool Configuration::DefaultValue::tls = true; - const bool Configuration::DefaultValue::tlsAllowInvalidHostnames = false; - const std::string Configuration::DefaultValue::tlsCaFile = ""; + // SSL/TLS options. Use checkboxes for boolean variables // need to add to UI + const bool Configuration::DefaultValue::tls = true; // changed instead of SSL mode; tls is TLS Encryption + const bool Configuration::DefaultValue::tlsAllowInvalidHostnames = false; // needs to be set to true for SSH; TLS Allow Invalid Hostnames + const std::string Configuration::DefaultValue::tlsCaFile = ""; //renamed from SSL CA file - // Schema Generation and Discovery options + // Schema Generation and Discovery options // need to add to UI const std::string Configuration::DefaultValue::scanMethod = "random"; const int32_t Configuration::DefaultValue::scanLimit = 1000; const std::string Configuration::DefaultValue::schemaName = "_default"; const bool Configuration::DefaultValue::refreshSchema = false; - // Internal SSH Tunnel options + // Internal SSH Tunnel options // need to add to UI const std::string Configuration::DefaultValue::sshUser = ""; const std::string Configuration::DefaultValue::sshHost = ""; const std::string Configuration::DefaultValue::sshPrivateKeyFile = ""; @@ -59,7 +59,7 @@ namespace ignite const bool Configuration::DefaultValue::sshStrictHostKeyChecking = true; const std::string Configuration::DefaultValue::sshKnownHostsFile = ""; - // Additional options + // Additional options // // need to add to UI const std::string Configuration::DefaultValue::appName = "Amazon DocumentDB ODBC Driver"; const int32_t Configuration::DefaultValue::loginTimeoutSec = 0; const std::string Configuration::DefaultValue::readPreference = ""; From f939e30b2692a6bcecdd3c6b6f6535e9d87ef1fd Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 18 Jan 2022 16:57:06 -0800 Subject: [PATCH 011/165] fix tls checkbox on Configuration Window fixed by updating ChildId in tlsCheckBox = CreateCheckBox --- .../odbc/system/ui/dsn_configuration_window.h | 53 +++++++-------- .../system/ui/dsn_configuration_window.cpp | 64 ++++++++++++------- 2 files changed, 68 insertions(+), 49 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index d528317d3..badfc42de 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -64,14 +64,14 @@ namespace ignite NESTED_TX_MODE_LABEL, NESTED_TX_MODE_COMBO_BOX, TLS_CHECK_BOX, - SSL_MODE_LABEL, - SSL_MODE_COMBO_BOX, - SSL_KEY_FILE_LABEL, - SSL_KEY_FILE_EDIT, - SSL_CERT_FILE_LABEL, - SSL_CERT_FILE_EDIT, - SSL_CA_FILE_LABEL, - SSL_CA_FILE_EDIT, + //SSL_MODE_LABEL, + //SSL_MODE_COMBO_BOX, + //SSL_KEY_FILE_LABEL, + //SSL_KEY_FILE_EDIT, + //SSL_CERT_FILE_LABEL, + //SSL_CERT_FILE_EDIT, + //SSL_CA_FILE_LABEL, + //SSL_CA_FILE_EDIT, USER_LABEL, USER_EDIT, PASSWORD_LABEL, @@ -280,31 +280,34 @@ namespace ignite std::auto_ptr cancelButton; /** TLS Encryption CheckBox. */ - std::auto_ptr< Window > tlsCheckBox; + std::auto_ptr tlsCheckBox; - /** SSL Mode label. */ - std::auto_ptr sslModeLabel; - /** SSL Mode ComboBox. */ - std::auto_ptr sslModeComboBox; - /** SSL Private Key File label. */ - std::auto_ptr sslKeyFileLabel; - /** SSL Private Key File edit. */ - std::auto_ptr sslKeyFileEdit; + ///** SSL Mode label. */ + //std::auto_ptr sslModeLabel; - /** SSL Certificate File label. */ - std::auto_ptr sslCertFileLabel; + ///** SSL Mode ComboBox. */ + //std::auto_ptr sslModeComboBox; - /** SSL Certificate File edit. */ - std::auto_ptr sslCertFileEdit; + ///** SSL Private Key File label. */ + //std::auto_ptr sslKeyFileLabel; - /** SSL Certificate Authority File label. */ - std::auto_ptr sslCaFileLabel; + ///** SSL Private Key File edit. */ + //std::auto_ptr sslKeyFileEdit; - /** SSL Certificate Authority File edit. */ - std::auto_ptr sslCaFileEdit; + ///** SSL Certificate File label. */ + //std::auto_ptr sslCertFileLabel; + + ///** SSL Certificate File edit. */ + //std::auto_ptr sslCertFileEdit; + + ///** SSL Certificate Authority File label. */ + //std::auto_ptr sslCaFileLabel; + + ///** SSL Certificate Authority File edit. */ + //std::auto_ptr sslCaFileEdit; /** User label. */ std::auto_ptr userLabel; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 6f2eab8c4..ff9a35948 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -221,7 +221,7 @@ namespace ignite int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) { // TODO: rename function name from Ssl to TLS after UI works - using ssl::SslMode; + //using ssl::SslMode; enum { LABEL_WIDTH = 120 }; @@ -235,7 +235,7 @@ namespace ignite int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; tlsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "TLS", ChildId::DISTRIBUTED_JOINS_CHECK_BOX, true); + "TLS", ChildId::TLS_CHECK_BOX, true); rowPos += INTERVAL + ROW_HEIGHT; @@ -472,7 +472,8 @@ namespace ignite break; } - case ChildId::TLS_CHECK_BOX: { + case ChildId::TLS_CHECK_BOX: + { tlsCheckBox->SetChecked(!tlsCheckBox->IsChecked()); break; @@ -485,14 +486,21 @@ namespace ignite std::string sslModeStr; sslModeComboBox->GetText(sslModeStr); - SslMode::Type sslMode = SslMode::FromString(sslModeStr, SslMode::DISABLE); + //case ChildId::SSL_MODE_COMBO_BOX: //-AL- may need to remove this later + //{ + // using ssl::SslMode; - sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - sslCaFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + // std::string sslModeStr; + // sslModeComboBox->GetText(sslModeStr); - break; - } + // SslMode::Type sslMode = SslMode::FromString(sslModeStr, SslMode::DISABLE); + + // sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + // sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + // sslCaFileEdit->SetEnabled(sslMode != SslMode::DISABLE); + + // break; + //} default: return false; @@ -585,28 +593,36 @@ namespace ignite void DsnConfigurationWindow::RetrieveSslParameters(config::Configuration& cfg) const { - std::string sslModeStr; - std::string sslKeyStr; - std::string sslCertStr; - std::string sslCaStr; - sslModeComboBox->GetText(sslModeStr); - sslKeyFileEdit->GetText(sslKeyStr); - sslCertFileEdit->GetText(sslCertStr); - sslCaFileEdit->GetText(sslCaStr); + bool tls = tlsCheckBox->IsChecked(); - LOG_MSG("Retrieving arguments:"); - LOG_MSG("SSL Mode: " << sslModeStr); - LOG_MSG("SSL Key: " << sslKeyStr); - LOG_MSG("SSL Certificate: " << sslCertStr); - LOG_MSG("SSL CA: " << sslCaStr); - ssl::SslMode::Type sslMode = ssl::SslMode::FromString(sslModeStr, ssl::SslMode::DISABLE); + LOG_MSG("TLS/SSL Encryption: " << (tls ? "true" : "false")); + + cfg.SetTls(tls); + + //std::string sslModeStr; + //std::string sslKeyStr; + //std::string sslCertStr; + //std::string sslCaStr; + + ////sslModeComboBox->GetText(sslModeStr); + ////sslKeyFileEdit->GetText(sslKeyStr); + ////sslCertFileEdit->GetText(sslCertStr); + ////sslCaFileEdit->GetText(sslCaStr); + + //LOG_MSG("Retrieving arguments:"); + //LOG_MSG("SSL Mode: " << sslModeStr); + //LOG_MSG("SSL Key: " << sslKeyStr); + //LOG_MSG("SSL Certificate: " << sslCertStr); + //LOG_MSG("SSL CA: " << sslCaStr); + + //ssl::SslMode::Type sslMode = ssl::SslMode::FromString(sslModeStr, ssl::SslMode::DISABLE); //cfg.SetSslMode(sslMode); //cfg.SetSslKeyFile(sslKeyStr); //cfg.SetSslCertFile(sslCertStr); - cfg.SetTlsCaFile(sslCaStr); + //cfg.SetTlsCaFile(sslCaStr); } void DsnConfigurationWindow::RetrieveAdditionalParameters(config::Configuration& cfg) const From 28950adb00307ad560dfb166d67467f7c202abf2 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 18 Jan 2022 16:58:12 -0800 Subject: [PATCH 012/165] add TlsAllowInvalidHostnames checkbox and TLS CA edit to the Configuration Window --- .../odbc/system/ui/dsn_configuration_window.h | 9 +++++ .../system/ui/dsn_configuration_window.cpp | 34 ++++++++++++++++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index badfc42de..eefce6894 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -64,6 +64,9 @@ namespace ignite NESTED_TX_MODE_LABEL, NESTED_TX_MODE_COMBO_BOX, TLS_CHECK_BOX, + TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, + TLS_CA_FILE_LABEL, + TLS_CA_FILE_EDIT, //SSL_MODE_LABEL, //SSL_MODE_COMBO_BOX, //SSL_KEY_FILE_LABEL, @@ -282,8 +285,14 @@ namespace ignite /** TLS Encryption CheckBox. */ std::auto_ptr tlsCheckBox; + /** TLS Allow Invalid Hostnames CheckBox. */ + std::auto_ptr< Window > tlsAllowInvalidHostnamesCheckBox; + /** TLS Certificate Authority File label. */ + std::auto_ptr tlsCaFileLabel; + /** TLS Certificate Authority File edit. */ + std::auto_ptr tlsCaFileEdit; ///** SSL Mode label. */ //std::auto_ptr sslModeLabel; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index ff9a35948..3addd1399 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -237,6 +237,19 @@ namespace ignite tlsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "TLS", ChildId::TLS_CHECK_BOX, true); + tlsAllowInvalidHostnamesCheckBox = CreateCheckBox( + labelPosX + checkBoxSize + INTERVAL, rowPos, + checkBoxSize, ROW_HEIGHT, "TLS Allow Invalid Hostnames", + ChildId::TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, false); + + rowPos += INTERVAL + ROW_HEIGHT; + + const char* val = config.GetTlsCaFile().c_str(); + tlsCaFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "TLS Certificate Authority:", ChildId::TLS_CA_FILE_LABEL); + tlsCaFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, + ChildId::TLS_CA_FILE_EDIT); + rowPos += INTERVAL + ROW_HEIGHT; //SslMode::Type sslMode = ssl::SslMode::REQUIRE; @@ -287,7 +300,9 @@ namespace ignite // rowPos += INTERVAL + ROW_HEIGHT; sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); + "TLS/SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); + + tlsCaFileEdit->SetEnabled(tlsCheckBox->IsChecked()); //sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE); //sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE); @@ -475,16 +490,18 @@ namespace ignite case ChildId::TLS_CHECK_BOX: { tlsCheckBox->SetChecked(!tlsCheckBox->IsChecked()); + tlsCaFileEdit->SetEnabled(tlsCheckBox->IsChecked()); break; } - case ChildId::SSL_MODE_COMBO_BOX: //-AL- may need to remove this later + + case ChildId::TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX: { - using ssl::SslMode; + tlsAllowInvalidHostnamesCheckBox->SetChecked(!tlsAllowInvalidHostnamesCheckBox->IsChecked()); - std::string sslModeStr; - sslModeComboBox->GetText(sslModeStr); + break; + } //case ChildId::SSL_MODE_COMBO_BOX: //-AL- may need to remove this later //{ @@ -595,11 +612,18 @@ namespace ignite { bool tls = tlsCheckBox->IsChecked(); + bool tlsAllowInvalidHostnames = tlsAllowInvalidHostnamesCheckBox->IsChecked(); + std::string tlsCaStr; + tlsCaFileEdit->GetText(tlsCaStr); LOG_MSG("TLS/SSL Encryption: " << (tls ? "true" : "false")); + LOG_MSG("tls Allow Invalid Hostnames: " << (tlsAllowInvalidHostnames ? "true" : "false")); + LOG_MSG("TLS CA: " << tlsCaStr); cfg.SetTls(tls); + cfg.SetTlsAllowInvalidHostnames(tlsAllowInvalidHostnames); + cfg.SetTlsCaFile(tlsCaStr); //std::string sslModeStr; //std::string sslKeyStr; From d5ae191a7241a1a3eb21b43902d932010dda2d3c Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 19 Jan 2022 09:22:54 -0800 Subject: [PATCH 013/165] Update configuration.cpp add comment to illustrate plan on what to do for the configuration window --- src/odbc/src/config/configuration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index e852bb652..d09cfa758 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -45,7 +45,7 @@ namespace ignite const bool Configuration::DefaultValue::tlsAllowInvalidHostnames = false; // needs to be set to true for SSH; TLS Allow Invalid Hostnames const std::string Configuration::DefaultValue::tlsCaFile = ""; //renamed from SSL CA file - // Schema Generation and Discovery options // need to add to UI + // Schema Generation and Discovery options // need to add to UI // I think I need a new group setting thing const std::string Configuration::DefaultValue::scanMethod = "random"; const int32_t Configuration::DefaultValue::scanLimit = 1000; const std::string Configuration::DefaultValue::schemaName = "_default"; From c06275eb37f57568009c6b175f285f855b962979 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 19 Jan 2022 10:39:02 -0800 Subject: [PATCH 014/165] Update dsn_configuration_window.cpp bugfix to make tlsCheckBox and tlsAllowInvalidHostnamesCheckBox read into the saved values --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 3addd1399..45128ea42 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -235,12 +235,13 @@ namespace ignite int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; tlsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "TLS", ChildId::TLS_CHECK_BOX, true); + "TLS", ChildId::TLS_CHECK_BOX, config.IsTls()); tlsAllowInvalidHostnamesCheckBox = CreateCheckBox( labelPosX + checkBoxSize + INTERVAL, rowPos, checkBoxSize, ROW_HEIGHT, "TLS Allow Invalid Hostnames", - ChildId::TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, false); + ChildId::TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, + config.IsTlsAllowInvalidHostnames()); rowPos += INTERVAL + ROW_HEIGHT; From f311e3bc7df1fd66d7be66c8e60170a41d078c18 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 19 Jan 2022 14:35:12 -0800 Subject: [PATCH 015/165] change defaultFetchSize to fetchSize in configuration.h --- .../include/ignite/odbc/config/configuration.h | 10 +++++----- src/odbc/src/config/configuration.cpp | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index c5a021c2d..695f257e7 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -137,7 +137,7 @@ namespace ignite // static const ProtocolVersion& protocolVersion; /** Default value for fetch results page size attribute. */ - static const int32_t defaultFetchSize; + static const int32_t fetchSize; /** Default value for nestedTxMode attribute. */ static const NestedTxMode::Type nestedTxMode; @@ -703,21 +703,21 @@ namespace ignite * * @return Fetch results page size. */ - int32_t GetDefaultFetchSize() const; + int32_t GetFetchSize() const; /** * Set fetch results page size. * * @param size Fetch results page size. */ - void SetDefaultFetchSize(int32_t size); + void SetFetchSize(int32_t size); /** * Check if the value set. * * @return @true if the value set. */ - bool IsDefaultFetchSizeSet() const; + bool IsFetchSizeSet() const; /** * Get argument map. @@ -816,7 +816,7 @@ namespace ignite SettableValue refreshSchema; /** Request and response page size. */ - SettableValue defaultFetchSize; + SettableValue fetchSize; }; template<> diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index d09cfa758..7ae42b733 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -65,7 +65,7 @@ namespace ignite const std::string Configuration::DefaultValue::readPreference = ""; const std::string Configuration::DefaultValue::replicaSet = ""; const bool Configuration::DefaultValue::retryReads = true; - const int32_t Configuration::DefaultValue::defaultFetchSize = 2000; + const int32_t Configuration::DefaultValue::fetchSize = 2000; const NestedTxMode::Type Configuration::DefaultValue::nestedTxMode = NestedTxMode::AI_ERROR; // remove @@ -96,7 +96,7 @@ namespace ignite scanLimit(DefaultValue::scanLimit), schemaName(DefaultValue::schemaName), refreshSchema(DefaultValue::refreshSchema), - defaultFetchSize(DefaultValue::defaultFetchSize) + fetchSize(DefaultValue::fetchSize) { // No-op. } @@ -519,19 +519,19 @@ namespace ignite return password.IsSet(); } - int32_t Configuration::GetDefaultFetchSize() const + int32_t Configuration::GetFetchSize() const { - return defaultFetchSize.GetValue(); + return fetchSize.GetValue(); } - void Configuration::SetDefaultFetchSize(int32_t size) + void Configuration::SetFetchSize(int32_t size) { - this->defaultFetchSize.SetValue(size); + this->fetchSize.SetValue(size); } - bool Configuration::IsDefaultFetchSizeSet() const + bool Configuration::IsFetchSizeSet() const { - return defaultFetchSize.IsSet(); + return fetchSize.IsSet(); } void Configuration::ToMap(ArgumentMap& res) const @@ -563,7 +563,7 @@ namespace ignite AddToMap(res, ConnectionStringParser::Key::scanLimit, scanLimit); AddToMap(res, ConnectionStringParser::Key::schemaName, schemaName); AddToMap(res, ConnectionStringParser::Key::refreshSchema, refreshSchema); - AddToMap(res, ConnectionStringParser::Key::defaultFetchSize, defaultFetchSize); + AddToMap(res, ConnectionStringParser::Key::fetchSize, fetchSize); } template<> From 8e79965abbcd7963659f191af288254878008cb3 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 19 Jan 2022 14:35:36 -0800 Subject: [PATCH 016/165] change Default DSN name to DocumentDB DSN --- src/odbc/src/config/configuration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 7ae42b733..a0d11bc0b 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -31,7 +31,7 @@ namespace ignite namespace config { - const std::string Configuration::DefaultValue::dsn = "Apache Ignite DSN"; + const std::string Configuration::DefaultValue::dsn = "DocumentDB DSN"; const std::string Configuration::DefaultValue::driver = "Apache Ignite"; const std::string Configuration::DefaultValue::database = ""; // renamed from Schema const std::string Configuration::DefaultValue::address = ""; // remove From a5cd10ee247a48ae93d4c56b8fad09effcca385e Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 19 Jan 2022 14:37:47 -0800 Subject: [PATCH 017/165] add App Name, Fetch Size, Read Preference, and login timeout to configuration window --- .../odbc/system/ui/dsn_configuration_window.h | 90 ++++-- .../system/ui/dsn_configuration_window.cpp | 283 +++++++++++------- 2 files changed, 242 insertions(+), 131 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index eefce6894..a5274cfdc 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -51,22 +51,30 @@ namespace ignite ADDRESS_LABEL, SCHEMA_EDIT, SCHEMA_LABEL, - PAGE_SIZE_EDIT, - PAGE_SIZE_LABEL, - DISTRIBUTED_JOINS_CHECK_BOX, - ENFORCE_JOIN_ORDER_CHECK_BOX, - REPLICATED_ONLY_CHECK_BOX, - COLLOCATED_CHECK_BOX, - LAZY_CHECK_BOX, - SKIP_REDUCER_ON_UPDATE_CHECK_BOX, + APP_NAME_EDIT, + APP_NAME_LABEL, + FETCH_SIZE_EDIT, + FETCH_SIZE_LABEL, + READ_PREFERENCE_EDIT, + READ_PREFERENCE_LABEL, + LOGIN_TIMEOUT_SEC_EDIT, + LOGIN_TIMEOUT_SEC_LABEL, + //PAGE_SIZE_EDIT, + //PAGE_SIZE_LABEL, + //DISTRIBUTED_JOINS_CHECK_BOX, + //ENFORCE_JOIN_ORDER_CHECK_BOX, + //REPLICATED_ONLY_CHECK_BOX, + //COLLOCATED_CHECK_BOX, + //LAZY_CHECK_BOX, + //SKIP_REDUCER_ON_UPDATE_CHECK_BOX, PROTOCOL_VERSION_LABEL, PROTOCOL_VERSION_COMBO_BOX, NESTED_TX_MODE_LABEL, NESTED_TX_MODE_COMBO_BOX, TLS_CHECK_BOX, TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, - TLS_CA_FILE_LABEL, TLS_CA_FILE_EDIT, + TLS_CA_FILE_LABEL, //SSL_MODE_LABEL, //SSL_MODE_COMBO_BOX, //SSL_KEY_FILE_LABEL, @@ -246,29 +254,53 @@ namespace ignite /** DSN schema edit field. */ std::auto_ptr schemaEdit; - /** DSN fetch page size edit field label. */ - std::auto_ptr pageSizeLabel; + /** Application name edit. */ + std::auto_ptr appNameEdit; + + /** Application name label. */ + std::auto_ptr appNameLabel; + + /** Login Timeout (seconds) edit. */ + std::auto_ptr loginTimeoutSecEdit; + + /** Login Timeout (seconds) label. */ + std::auto_ptr loginTimeoutSecLabel; + + /** Read preference edit. */ + std::auto_ptr readPreferenceEdit; + + /** Read preference label. */ + std::auto_ptr< Window > readPreferenceLabel; + + /** Fetch size edit. */ + std::auto_ptr fetchSizeEdit; + + /** Fetch size label. */ + std::auto_ptr fetchSizeLabel; + + ///** DSN fetch page size edit field label. */ + //std::auto_ptr pageSizeLabel; - /** DSN fetch page size edit field. */ - std::auto_ptr pageSizeEdit; + ///** DSN fetch page size edit field. */ + //std::auto_ptr pageSizeEdit; - /** Distributed joins CheckBox. */ - std::auto_ptr distributedJoinsCheckBox; + ///** Distributed joins CheckBox. */ + //std::auto_ptr distributedJoinsCheckBox; - /** Enforce join order CheckBox. */ - std::auto_ptr enforceJoinOrderCheckBox; + ///** Enforce join order CheckBox. */ + //std::auto_ptr enforceJoinOrderCheckBox; - /** Replicated only CheckBox. */ - std::auto_ptr replicatedOnlyCheckBox; + ///** Replicated only CheckBox. */ + //std::auto_ptr replicatedOnlyCheckBox; - /** Collocated CheckBox. */ - std::auto_ptr collocatedCheckBox; + ///** Collocated CheckBox. */ + //std::auto_ptr collocatedCheckBox; - /** Lazy CheckBox. */ - std::auto_ptr lazyCheckBox; + ///** Lazy CheckBox. */ + //std::auto_ptr lazyCheckBox; - /** Update on server CheckBox. */ - std::auto_ptr skipReducerOnUpdateCheckBox; + ///** Update on server CheckBox. */ + //std::auto_ptr skipReducerOnUpdateCheckBox; /** Protocol version edit field. */ std::auto_ptr protocolVersionLabel; @@ -330,11 +362,11 @@ namespace ignite /** Password edit. */ std::auto_ptr passwordEdit; - /** Nested transaction mode label. */ - std::auto_ptr nestedTxModeLabel; + ///** Nested transaction mode label. */ + //std::auto_ptr nestedTxModeLabel; - /** Nested transaction mode combo box. */ - std::auto_ptr nestedTxModeComboBox; + ///** Nested transaction mode combo box. */ + //std::auto_ptr nestedTxModeComboBox; /** Configuration. */ config::Configuration& config; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 45128ea42..33f359232 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -41,19 +41,25 @@ namespace ignite sslSettingsGroupBox(), // has a create... function defined tlsCheckBox(), authSettingsGroupBox(), - // additionalSettingsGroupBox(), + additionalSettingsGroupBox(), nameLabel(), nameEdit(), addressLabel(), addressEdit(), schemaLabel(), schemaEdit(), - pageSizeLabel(), - pageSizeEdit(), - distributedJoinsCheckBox(), - enforceJoinOrderCheckBox(), - replicatedOnlyCheckBox(), - // collocatedCheckBox(), // -AL- after commenting this out, the checkbox is intact? + appNameLabel(), + appNameEdit(), + readPreferenceLabel(), + readPreferenceEdit(), + fetchSizeLabel(), + fetchSizeEdit(), + // pageSizeLabel(), + // pageSizeEdit(), + //distributedJoinsCheckBox(), + //enforceJoinOrderCheckBox(), + //replicatedOnlyCheckBox(), + //collocatedCheckBox(), // -AL- after commenting this out, the checkbox is intact? // checkbox is created in function DsnConfigurationWindow::CreateAdditionalSettingsGroup protocolVersionLabel(), protocolVersionComboBox(), @@ -61,7 +67,7 @@ namespace ignite userEdit(), passwordLabel(), passwordEdit(), - nestedTxModeComboBox(), + //nestedTxModeComboBox(), okButton(), cancelButton(), config(config), @@ -314,7 +320,7 @@ namespace ignite int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) { - enum { LABEL_WIDTH = 130 }; + enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also change it to the same int labelPosX = posX + INTERVAL; @@ -323,28 +329,69 @@ namespace ignite int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; - ProtocolVersion version = ProtocolVersion::GetCurrent(); + //ProtocolVersion version = ProtocolVersion::GetCurrent(); - if (!version.IsSupported()) - version = ProtocolVersion::GetCurrent(); + //if (!version.IsSupported()) + // version = ProtocolVersion::GetCurrent(); int rowPos = posY + 2 * INTERVAL; - std::string tmp = common::LexicalCast(1000); - const char* val = tmp.c_str(); - pageSizeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, - ROW_HEIGHT, "Page size:", ChildId::PAGE_SIZE_LABEL); + const char* val = config.GetApplicationName().c_str(); + + appNameLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, + ROW_HEIGHT, "Application Name:", ChildId::APP_NAME_LABEL); + appNameEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, ChildId::APP_NAME_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + std::string tmp = common::LexicalCast< std::string >(config.GetLoginTimeoutSeconds()); + val = tmp.c_str(); + loginTimeoutSecLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, + ROW_HEIGHT, "Login Timeout (s):", ChildId::LOGIN_TIMEOUT_SEC_LABEL); + + loginTimeoutSecEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, ChildId::LOGIN_TIMEOUT_SEC_EDIT, ES_NUMBER); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetReadPreference().c_str(); + + readPreferenceLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Read preference:", ChildId::READ_PREFERENCE_LABEL); + readPreferenceEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, + ChildId::READ_PREFERENCE_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + tmp = common::LexicalCast(config.GetFetchSize()); + val = tmp.c_str(); + fetchSizeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, + ROW_HEIGHT, "Fetch size:", ChildId::FETCH_SIZE_LABEL); - pageSizeEdit = CreateEdit(editPosX, rowPos, editSizeX, - ROW_HEIGHT, val, ChildId::PAGE_SIZE_EDIT, ES_NUMBER); + fetchSizeEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, ChildId::FETCH_SIZE_EDIT, ES_NUMBER); rowPos += INTERVAL + ROW_HEIGHT; - nestedTxModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Nested Transaction Mode:", ChildId::NESTED_TX_MODE_LABEL); - nestedTxModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, - "", ChildId::NESTED_TX_MODE_COMBO_BOX); + //std::string tmp = common::LexicalCast< std::string >(1000); + //const char* val = tmp.c_str(); + //pageSizeLabel = + // CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + // "Page size:", ChildId::PAGE_SIZE_LABEL); + //pageSizeEdit = + // CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, + // ChildId::PAGE_SIZE_EDIT, ES_NUMBER); + + //rowPos += INTERVAL + ROW_HEIGHT; + + //nestedTxModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + // "Nested Transaction Mode:", ChildId::NESTED_TX_MODE_LABEL); + //nestedTxModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, + // "", ChildId::NESTED_TX_MODE_COMBO_BOX); + + /* int id = 0; const NestedTxMode::ModeSet& supported = NestedTxMode::GetValidValues(); @@ -353,52 +400,52 @@ namespace ignite { nestedTxModeComboBox->AddString(NestedTxMode::ToString(*it)); - /* if (*it == config.GetNestedTxMode()) - nestedTxModeComboBox->SetSelection(id); */ + if (*it == config.GetNestedTxMode()) + nestedTxModeComboBox->SetSelection(id); - ++id; - } - - nestedTxModeComboBox->SetEnabled(version >= ProtocolVersion::VERSION_2_5_0); + // ++id; + //} + //*/ + //nestedTxModeComboBox->SetEnabled(version >= ProtocolVersion::VERSION_2_5_0); - rowPos += INTERVAL + ROW_HEIGHT; + //rowPos += INTERVAL + ROW_HEIGHT; - distributedJoinsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Distributed Joins", ChildId::DISTRIBUTED_JOINS_CHECK_BOX, false); + //distributedJoinsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, + // "Distributed Joins", ChildId::DISTRIBUTED_JOINS_CHECK_BOX, false); - enforceJoinOrderCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, - rowPos, checkBoxSize, ROW_HEIGHT, "Enforce Join Order", - ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX, false); + //enforceJoinOrderCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, + // rowPos, checkBoxSize, ROW_HEIGHT, "Enforce Join Order", + // ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX, false); - rowPos += ROW_HEIGHT; + //rowPos += ROW_HEIGHT; - replicatedOnlyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Replicated Only", ChildId::REPLICATED_ONLY_CHECK_BOX, false); - - collocatedCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, checkBoxSize, - ROW_HEIGHT, "Collocated", ChildId::COLLOCATED_CHECK_BOX, false); + //replicatedOnlyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, + // "Replicated Only", ChildId::REPLICATED_ONLY_CHECK_BOX, false); + // + //collocatedCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, checkBoxSize, + // ROW_HEIGHT, "Collocated", ChildId::COLLOCATED_CHECK_BOX, false); - rowPos += ROW_HEIGHT; + //rowPos += ROW_HEIGHT; - lazyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Lazy", ChildId::LAZY_CHECK_BOX, false); + //lazyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, + // "Lazy", ChildId::LAZY_CHECK_BOX, false); - lazyCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_1_5); + ////lazyCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_1_5); - skipReducerOnUpdateCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, - checkBoxSize, ROW_HEIGHT, "Skip reducer on update", ChildId::SKIP_REDUCER_ON_UPDATE_CHECK_BOX, - false); + //skipReducerOnUpdateCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, + // checkBoxSize, ROW_HEIGHT, "Skip reducer on update", ChildId::SKIP_REDUCER_ON_UPDATE_CHECK_BOX, + // false); - skipReducerOnUpdateCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_3_0); + //skipReducerOnUpdateCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_3_0); - rowPos += ROW_HEIGHT + INTERVAL; + //rowPos += ROW_HEIGHT + INTERVAL; additionalSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "Additional settings", ChildId::ADDITIONAL_SETTINGS_GROUP_BOX); return rowPos - posY; } - // -AL- I'm not changing this one yet. + bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) @@ -433,60 +480,60 @@ namespace ignite break; } - case ChildId::DISTRIBUTED_JOINS_CHECK_BOX: - { - distributedJoinsCheckBox->SetChecked(!distributedJoinsCheckBox->IsChecked()); + //case ChildId::DISTRIBUTED_JOINS_CHECK_BOX: + //{ + // distributedJoinsCheckBox->SetChecked(!distributedJoinsCheckBox->IsChecked()); - break; - } + // break; + //} - case ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX: - { - enforceJoinOrderCheckBox->SetChecked(!enforceJoinOrderCheckBox->IsChecked()); + //case ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX: + //{ + // enforceJoinOrderCheckBox->SetChecked(!enforceJoinOrderCheckBox->IsChecked()); - break; - } + // break; + //} - case ChildId::REPLICATED_ONLY_CHECK_BOX: - { - replicatedOnlyCheckBox->SetChecked(!replicatedOnlyCheckBox->IsChecked()); + //case ChildId::REPLICATED_ONLY_CHECK_BOX: + //{ + // replicatedOnlyCheckBox->SetChecked(!replicatedOnlyCheckBox->IsChecked()); - break; - } + // break; + //} - case ChildId::COLLOCATED_CHECK_BOX: - { - collocatedCheckBox->SetChecked(!collocatedCheckBox->IsChecked()); + //case ChildId::COLLOCATED_CHECK_BOX: + //{ + // collocatedCheckBox->SetChecked(!collocatedCheckBox->IsChecked()); - break; - } + // break; + //} - case ChildId::LAZY_CHECK_BOX: - { - lazyCheckBox->SetChecked(!lazyCheckBox->IsChecked()); + //case ChildId::LAZY_CHECK_BOX: + //{ + // lazyCheckBox->SetChecked(!lazyCheckBox->IsChecked()); - break; - } + // break; + //} - case ChildId::SKIP_REDUCER_ON_UPDATE_CHECK_BOX: - { - skipReducerOnUpdateCheckBox->SetChecked(!skipReducerOnUpdateCheckBox->IsChecked()); + //case ChildId::SKIP_REDUCER_ON_UPDATE_CHECK_BOX: + //{ + // skipReducerOnUpdateCheckBox->SetChecked(!skipReducerOnUpdateCheckBox->IsChecked()); - break; - } + // break; + //} - case ChildId::PROTOCOL_VERSION_COMBO_BOX: - { - std::string versionStr; - protocolVersionComboBox->GetText(versionStr); + //case ChildId::PROTOCOL_VERSION_COMBO_BOX: + //{ + // std::string versionStr; + // protocolVersionComboBox->GetText(versionStr); - ProtocolVersion version = ProtocolVersion::FromString(versionStr); - lazyCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_1_5); - skipReducerOnUpdateCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_3_0); - nestedTxModeComboBox->SetEnabled(version >= ProtocolVersion::VERSION_2_5_0); + // ProtocolVersion version = ProtocolVersion::FromString(versionStr); + // lazyCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_1_5); + // skipReducerOnUpdateCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_3_0); + // nestedTxModeComboBox->SetEnabled(version >= ProtocolVersion::VERSION_2_5_0); - break; - } + // break; + //} case ChildId::TLS_CHECK_BOX: { @@ -618,9 +665,9 @@ namespace ignite tlsCaFileEdit->GetText(tlsCaStr); - LOG_MSG("TLS/SSL Encryption: " << (tls ? "true" : "false")); - LOG_MSG("tls Allow Invalid Hostnames: " << (tlsAllowInvalidHostnames ? "true" : "false")); - LOG_MSG("TLS CA: " << tlsCaStr); + LOG_MSG("TLS/SSL Encryption: " << (tls ? "true" : "false")); + LOG_MSG("tls Allow Invalid Hostnames: " << (tlsAllowInvalidHostnames ? "true" : "false")); + LOG_MSG("TLS CA: " << tlsCaStr); cfg.SetTls(tls); cfg.SetTlsAllowInvalidHostnames(tlsAllowInvalidHostnames); @@ -652,18 +699,45 @@ namespace ignite void DsnConfigurationWindow::RetrieveAdditionalParameters(config::Configuration& cfg) const { - std::string pageSizeStr; - pageSizeEdit->GetText(pageSizeStr); + std::string appNameStr; + std::string readPreferenceStr; + + appNameEdit->GetText(appNameStr); + readPreferenceEdit->GetText(readPreferenceStr); + + std::string loginTimeoutSecStr; + + loginTimeoutSecEdit->GetText(loginTimeoutSecStr); + + int32_t loginTimeoutSec = + common::LexicalCast< int32_t >(loginTimeoutSecStr); + + if (loginTimeoutSec <= 0) + loginTimeoutSec = config.GetLoginTimeoutSeconds(); + + std::string fetchSizeStr; + + fetchSizeEdit->GetText(fetchSizeStr); + + int32_t fetchSize = + common::LexicalCast< int32_t >(fetchSizeStr); + + if (fetchSize <= 0) + fetchSize = config.GetFetchSize(); + + //std::string pageSizeStr; + + //pageSizeEdit->GetText(pageSizeStr); - int32_t pageSize = common::LexicalCast(pageSizeStr); + //int32_t pageSize = common::LexicalCast(pageSizeStr); - if (pageSize <= 0) - pageSize = config.GetDefaultFetchSize(); + //if (pageSize <= 0) + // pageSize = config.GetPageSize(); - std::string nestedTxModeStr; + //std::string nestedTxModeStr; - nestedTxModeComboBox->GetText(nestedTxModeStr); + //nestedTxModeComboBox->GetText(nestedTxModeStr); // unnecessary code is commented out -AL- //NestedTxMode::Type mode = NestedTxMode::FromString(nestedTxModeStr, config.GetNestedTxMode()); @@ -676,7 +750,10 @@ namespace ignite //bool skipReducerOnUpdate = skipReducerOnUpdateCheckBox->IsChecked(); LOG_MSG("Retrieving arguments:"); - LOG_MSG("Page size: " << pageSize); + LOG_MSG("App name: " << appNameStr); + LOG_MSG("Login timeout (seconds): " << loginTimeoutSecStr); + LOG_MSG("Read preference: " << readPreferenceStr); + LOG_MSG("Fetch size: " << fetchSize); //LOG_MSG("Nested TX Mode: " << NestedTxMode::ToString(mode)); //LOG_MSG("Distributed Joins: " << (distributedJoins ? "true" : "false")); //LOG_MSG("Enforce Join Order: " << (enforceJoinOrder ? "true" : "false")); @@ -685,7 +762,9 @@ namespace ignite //LOG_MSG("Lazy: " << (lazy ? "true" : "false")); //LOG_MSG("Skip reducer on update: " << (skipReducerOnUpdate ? "true" : "false")); - cfg.SetDefaultFetchSize(pageSize); + cfg.SetApplicationName(appNameStr); + cfg.SetLoginTimeoutSeconds(loginTimeoutSec); + cfg.SetFetchSize(fetchSize); //cfg.SetNestedTxMode(mode); //cfg.SetDistributedJoins(distributedJoins); //cfg.SetEnforceJoinOrder(enforceJoinOrder); From 2bcd2a492bd69fbde5de986a03c5a407a729ba47 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 19 Jan 2022 15:06:33 -0800 Subject: [PATCH 018/165] [AD-522] bugfix - change DefaultFetchSize to fetchSize in all related files to be consistent with configuration.h Files that had the change connection_string_parser.cpp, connection_string_parser.h, dsn_config.cpp, batch_query.cpp, data_query.cpp. --- .../ignite/odbc/config/connection_string_parser.h | 2 +- src/odbc/src/config/connection_string_parser.cpp | 6 +++--- src/odbc/src/dsn_config.cpp | 10 +++++----- src/odbc/src/query/batch_query.cpp | 2 +- src/odbc/src/query/data_query.cpp | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index 27e4f48d2..ba557d6c3 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -120,7 +120,7 @@ namespace ignite static const std::string protocolVersion; /** Connection attribute keyword for fetch results page size attribute. */ - static const std::string defaultFetchSize; + static const std::string fetchSize; /** Connection attribute keyword for sslMode attribute. */ static const std::string sslMode; diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index 308bb225b..a05e2a530 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -57,7 +57,7 @@ namespace ignite const std::string ConnectionStringParser::Key::scanLimit = "scan_limit"; const std::string ConnectionStringParser::Key::schemaName = "schema_name"; const std::string ConnectionStringParser::Key::refreshSchema = "refresh_schema"; - const std::string ConnectionStringParser::Key::defaultFetchSize = "default_fetch_size"; + const std::string ConnectionStringParser::Key::fetchSize = "fetch_size"; const std::string ConnectionStringParser::Key::uid = "uid"; const std::string ConnectionStringParser::Key::pwd = "pwd"; @@ -399,7 +399,7 @@ namespace ignite cfg.SetTls(res == BoolParseResult::AI_TRUE); } - else if (lKey == Key::defaultFetchSize) + else if (lKey == Key::fetchSize) { if (!common::AllDigits(value)) { @@ -443,7 +443,7 @@ namespace ignite return; } - cfg.SetDefaultFetchSize(static_cast(numValue)); + cfg.SetFetchSize(static_cast(numValue)); } else if (lKey == Key::tlsCaFile) { diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 6526a38bd..9b02548ed 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -219,7 +219,7 @@ namespace ignite if (scanLimit.IsSet() && !config.IsScanLimitSet() && scanLimit.GetValue() > 0) - config.SetDefaultFetchSize(scanLimit.GetValue()); + config.SetFetchSize(scanLimit.GetValue()); SettableValue schemaName = ReadDsnString(dsn, ConnectionStringParser::Key::schemaName); @@ -231,11 +231,11 @@ namespace ignite if (refreshSchema.IsSet() && !config.IsSchemaRefreshSet()) config.SetSchemaRefresh(refreshSchema.GetValue()); - SettableValue defaultFetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::defaultFetchSize); + SettableValue fetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::fetchSize); - if (defaultFetchSize.IsSet() && !config.IsDefaultFetchSizeSet() - && defaultFetchSize.GetValue() > 0) - config.SetDefaultFetchSize(defaultFetchSize.GetValue()); + if (fetchSize.IsSet() && !config.IsFetchSizeSet() + && fetchSize.GetValue() > 0) + config.SetFetchSize(fetchSize.GetValue()); } } } diff --git a/src/odbc/src/query/batch_query.cpp b/src/odbc/src/query/batch_query.cpp index 7390b4f59..6a82d690e 100644 --- a/src/odbc/src/query/batch_query.cpp +++ b/src/odbc/src/query/batch_query.cpp @@ -52,7 +52,7 @@ namespace ignite if (executed) Close(); - int32_t maxPageSize = connection.GetConfiguration().GetDefaultFetchSize(); + int32_t maxPageSize = connection.GetConfiguration().GetFetchSize(); int32_t rowNum = params.GetParamSetSize(); SqlResult::Type res; diff --git a/src/odbc/src/query/data_query.cpp b/src/odbc/src/query/data_query.cpp index d5c4d6a6d..28a9ab72f 100644 --- a/src/odbc/src/query/data_query.cpp +++ b/src/odbc/src/query/data_query.cpp @@ -193,7 +193,7 @@ namespace ignite if (affected >= 0) return affected; - return connection.GetConfiguration().GetDefaultFetchSize(); + return connection.GetConfiguration().GetFetchSize(); } SqlResult::Type DataQuery::NextResultSet() @@ -320,7 +320,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); + QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetFetchSize()); QueryFetchResponse rsp(*resultPage); try @@ -361,7 +361,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); + QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetFetchSize()); QueryMoreResultsResponse rsp(*resultPage); try From eb03b9231c1d9f4d4b793fa8402d1fc2a79222eb Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 19 Jan 2022 15:24:07 -0800 Subject: [PATCH 019/165] [AD-522] save read preference settings --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 33f359232..20355a1d7 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -764,6 +764,7 @@ namespace ignite cfg.SetApplicationName(appNameStr); cfg.SetLoginTimeoutSeconds(loginTimeoutSec); + cfg.SetReadPreference(readPreferenceStr); cfg.SetFetchSize(fetchSize); //cfg.SetNestedTxMode(mode); //cfg.SetDistributedJoins(distributedJoins); From 0401433e1f9756c3a02063725c4b5d04dc2dabfa Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 19 Jan 2022 16:23:09 -0800 Subject: [PATCH 020/165] [AD-522] remove commented out code --- .../odbc/system/ui/dsn_configuration_window.h | 83 +----- .../system/ui/dsn_configuration_window.cpp | 272 +----------------- 2 files changed, 15 insertions(+), 340 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index a5274cfdc..27df1d8ba 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -53,20 +53,12 @@ namespace ignite SCHEMA_LABEL, APP_NAME_EDIT, APP_NAME_LABEL, - FETCH_SIZE_EDIT, - FETCH_SIZE_LABEL, - READ_PREFERENCE_EDIT, - READ_PREFERENCE_LABEL, LOGIN_TIMEOUT_SEC_EDIT, LOGIN_TIMEOUT_SEC_LABEL, - //PAGE_SIZE_EDIT, - //PAGE_SIZE_LABEL, - //DISTRIBUTED_JOINS_CHECK_BOX, - //ENFORCE_JOIN_ORDER_CHECK_BOX, - //REPLICATED_ONLY_CHECK_BOX, - //COLLOCATED_CHECK_BOX, - //LAZY_CHECK_BOX, - //SKIP_REDUCER_ON_UPDATE_CHECK_BOX, + READ_PREFERENCE_EDIT, + READ_PREFERENCE_LABEL, + FETCH_SIZE_EDIT, + FETCH_SIZE_LABEL, PROTOCOL_VERSION_LABEL, PROTOCOL_VERSION_COMBO_BOX, NESTED_TX_MODE_LABEL, @@ -75,14 +67,6 @@ namespace ignite TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, TLS_CA_FILE_EDIT, TLS_CA_FILE_LABEL, - //SSL_MODE_LABEL, - //SSL_MODE_COMBO_BOX, - //SSL_KEY_FILE_LABEL, - //SSL_KEY_FILE_EDIT, - //SSL_CERT_FILE_LABEL, - //SSL_CERT_FILE_EDIT, - //SSL_CA_FILE_LABEL, - //SSL_CA_FILE_EDIT, USER_LABEL, USER_EDIT, PASSWORD_LABEL, @@ -263,44 +247,21 @@ namespace ignite /** Login Timeout (seconds) edit. */ std::auto_ptr loginTimeoutSecEdit; - /** Login Timeout (seconds) label. */ + /** Login Timeout (seconds) label. */ std::auto_ptr loginTimeoutSecLabel; /** Read preference edit. */ std::auto_ptr readPreferenceEdit; /** Read preference label. */ - std::auto_ptr< Window > readPreferenceLabel; - - /** Fetch size edit. */ - std::auto_ptr fetchSizeEdit; - - /** Fetch size label. */ - std::auto_ptr fetchSizeLabel; - - ///** DSN fetch page size edit field label. */ - //std::auto_ptr pageSizeLabel; - - ///** DSN fetch page size edit field. */ - //std::auto_ptr pageSizeEdit; + std::auto_ptr readPreferenceLabel; - ///** Distributed joins CheckBox. */ - //std::auto_ptr distributedJoinsCheckBox; ///** Enforce join order CheckBox. */ //std::auto_ptr enforceJoinOrderCheckBox; - ///** Replicated only CheckBox. */ - //std::auto_ptr replicatedOnlyCheckBox; - ///** Collocated CheckBox. */ - //std::auto_ptr collocatedCheckBox; - ///** Lazy CheckBox. */ - //std::auto_ptr lazyCheckBox; - - ///** Update on server CheckBox. */ - //std::auto_ptr skipReducerOnUpdateCheckBox; /** Protocol version edit field. */ std::auto_ptr protocolVersionLabel; @@ -318,7 +279,7 @@ namespace ignite std::auto_ptr tlsCheckBox; /** TLS Allow Invalid Hostnames CheckBox. */ - std::auto_ptr< Window > tlsAllowInvalidHostnamesCheckBox; + std::auto_ptr tlsAllowInvalidHostnamesCheckBox; /** TLS Certificate Authority File label. */ std::auto_ptr tlsCaFileLabel; @@ -326,30 +287,6 @@ namespace ignite /** TLS Certificate Authority File edit. */ std::auto_ptr tlsCaFileEdit; - ///** SSL Mode label. */ - //std::auto_ptr sslModeLabel; - - ///** SSL Mode ComboBox. */ - //std::auto_ptr sslModeComboBox; - - ///** SSL Private Key File label. */ - //std::auto_ptr sslKeyFileLabel; - - ///** SSL Private Key File edit. */ - //std::auto_ptr sslKeyFileEdit; - - ///** SSL Certificate File label. */ - //std::auto_ptr sslCertFileLabel; - - ///** SSL Certificate File edit. */ - //std::auto_ptr sslCertFileEdit; - - ///** SSL Certificate Authority File label. */ - //std::auto_ptr sslCaFileLabel; - - ///** SSL Certificate Authority File edit. */ - //std::auto_ptr sslCaFileEdit; - /** User label. */ std::auto_ptr userLabel; @@ -362,12 +299,6 @@ namespace ignite /** Password edit. */ std::auto_ptr passwordEdit; - ///** Nested transaction mode label. */ - //std::auto_ptr nestedTxModeLabel; - - ///** Nested transaction mode combo box. */ - //std::auto_ptr nestedTxModeComboBox; - /** Configuration. */ config::Configuration& config; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 20355a1d7..fe7e0239b 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -54,20 +54,12 @@ namespace ignite readPreferenceEdit(), fetchSizeLabel(), fetchSizeEdit(), - // pageSizeLabel(), - // pageSizeEdit(), - //distributedJoinsCheckBox(), - //enforceJoinOrderCheckBox(), - //replicatedOnlyCheckBox(), - //collocatedCheckBox(), // -AL- after commenting this out, the checkbox is intact? - // checkbox is created in function DsnConfigurationWindow::CreateAdditionalSettingsGroup protocolVersionLabel(), protocolVersionComboBox(), userLabel(), userEdit(), passwordLabel(), passwordEdit(), - //nestedTxModeComboBox(), okButton(), cancelButton(), config(config), @@ -227,8 +219,7 @@ namespace ignite int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) { // TODO: rename function name from Ssl to TLS after UI works - //using ssl::SslMode; - + enum { LABEL_WIDTH = 120 }; int labelPosX = posX + INTERVAL; @@ -259,62 +250,11 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - //SslMode::Type sslMode = ssl::SslMode::REQUIRE; - //std::string sslModeStr = SslMode::ToString(sslMode); - - //const char* val = sslModeStr.c_str(); - - //sslModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - // "SSL Mode:", ChildId::SSL_MODE_LABEL); - //sslModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, - // "", ChildId::SSL_MODE_COMBO_BOX); - - //sslModeComboBox->AddString("disable"); - //sslModeComboBox->AddString("require"); - - //sslModeComboBox->SetSelection(sslMode); // set default value to require -AL- - - //rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight I believe - - //val = config.GetTlsCaFile().c_str(); - //sslKeyFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - // "SSL Private Key:", ChildId::SSL_KEY_FILE_LABEL); - //sslKeyFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, - // val, ChildId::SSL_KEY_FILE_EDIT); - - //SHAutoComplete(sslKeyFileEdit->GetHandle(), SHACF_DEFAULT); - - //rowPos += INTERVAL + ROW_HEIGHT; - - //val = config.GetTlsCaFile().c_str(); - //sslCertFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - // "SSL Certificate:", ChildId::SSL_CERT_FILE_LABEL); - //sslCertFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, - // val, ChildId::SSL_CERT_FILE_EDIT); - - //SHAutoComplete(sslCertFileEdit->GetHandle(), SHACF_DEFAULT); - - // rowPos += INTERVAL + ROW_HEIGHT; - - //val = config.GetTlsCaFile().c_str(); - //sslCaFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - // "SSL Certificate Authority:", ChildId::SSL_CA_FILE_LABEL); - //sslCaFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, - // val, ChildId::SSL_CA_FILE_EDIT); - - //SHAutoComplete(sslCaFileEdit->GetHandle(), SHACF_DEFAULT); - - // rowPos += INTERVAL + ROW_HEIGHT; - sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "TLS/SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); tlsCaFileEdit->SetEnabled(tlsCheckBox->IsChecked()); - //sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - //sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - //sslCaFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - return rowPos - posY; } @@ -329,11 +269,6 @@ namespace ignite int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; - //ProtocolVersion version = ProtocolVersion::GetCurrent(); - - //if (!version.IsSupported()) - // version = ProtocolVersion::GetCurrent(); - int rowPos = posY + 2 * INTERVAL; const char* val = config.GetApplicationName().c_str(); @@ -374,72 +309,6 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - //std::string tmp = common::LexicalCast< std::string >(1000); - //const char* val = tmp.c_str(); - //pageSizeLabel = - // CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - // "Page size:", ChildId::PAGE_SIZE_LABEL); - - //pageSizeEdit = - // CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, - // ChildId::PAGE_SIZE_EDIT, ES_NUMBER); - - //rowPos += INTERVAL + ROW_HEIGHT; - - //nestedTxModeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - // "Nested Transaction Mode:", ChildId::NESTED_TX_MODE_LABEL); - //nestedTxModeComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, - // "", ChildId::NESTED_TX_MODE_COMBO_BOX); - - /* - int id = 0; - - const NestedTxMode::ModeSet& supported = NestedTxMode::GetValidValues(); - - for (NestedTxMode::ModeSet::const_iterator it = supported.begin(); it != supported.end(); ++it) - { - nestedTxModeComboBox->AddString(NestedTxMode::ToString(*it)); - - if (*it == config.GetNestedTxMode()) - nestedTxModeComboBox->SetSelection(id); - - // ++id; - //} - //*/ - //nestedTxModeComboBox->SetEnabled(version >= ProtocolVersion::VERSION_2_5_0); - - //rowPos += INTERVAL + ROW_HEIGHT; - - //distributedJoinsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - // "Distributed Joins", ChildId::DISTRIBUTED_JOINS_CHECK_BOX, false); - - //enforceJoinOrderCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, - // rowPos, checkBoxSize, ROW_HEIGHT, "Enforce Join Order", - // ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX, false); - - //rowPos += ROW_HEIGHT; - - //replicatedOnlyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - // "Replicated Only", ChildId::REPLICATED_ONLY_CHECK_BOX, false); - // - //collocatedCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, checkBoxSize, - // ROW_HEIGHT, "Collocated", ChildId::COLLOCATED_CHECK_BOX, false); - - //rowPos += ROW_HEIGHT; - - //lazyCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - // "Lazy", ChildId::LAZY_CHECK_BOX, false); - - ////lazyCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_1_5); - - //skipReducerOnUpdateCheckBox = CreateCheckBox(labelPosX + checkBoxSize + INTERVAL, rowPos, - // checkBoxSize, ROW_HEIGHT, "Skip reducer on update", ChildId::SKIP_REDUCER_ON_UPDATE_CHECK_BOX, - // false); - - //skipReducerOnUpdateCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_3_0); - - //rowPos += ROW_HEIGHT + INTERVAL; - additionalSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "Additional settings", ChildId::ADDITIONAL_SETTINGS_GROUP_BOX); @@ -480,61 +349,6 @@ namespace ignite break; } - //case ChildId::DISTRIBUTED_JOINS_CHECK_BOX: - //{ - // distributedJoinsCheckBox->SetChecked(!distributedJoinsCheckBox->IsChecked()); - - // break; - //} - - //case ChildId::ENFORCE_JOIN_ORDER_CHECK_BOX: - //{ - // enforceJoinOrderCheckBox->SetChecked(!enforceJoinOrderCheckBox->IsChecked()); - - // break; - //} - - //case ChildId::REPLICATED_ONLY_CHECK_BOX: - //{ - // replicatedOnlyCheckBox->SetChecked(!replicatedOnlyCheckBox->IsChecked()); - - // break; - //} - - //case ChildId::COLLOCATED_CHECK_BOX: - //{ - // collocatedCheckBox->SetChecked(!collocatedCheckBox->IsChecked()); - - // break; - //} - - //case ChildId::LAZY_CHECK_BOX: - //{ - // lazyCheckBox->SetChecked(!lazyCheckBox->IsChecked()); - - // break; - //} - - //case ChildId::SKIP_REDUCER_ON_UPDATE_CHECK_BOX: - //{ - // skipReducerOnUpdateCheckBox->SetChecked(!skipReducerOnUpdateCheckBox->IsChecked()); - - // break; - //} - - //case ChildId::PROTOCOL_VERSION_COMBO_BOX: - //{ - // std::string versionStr; - // protocolVersionComboBox->GetText(versionStr); - - // ProtocolVersion version = ProtocolVersion::FromString(versionStr); - // lazyCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_1_5); - // skipReducerOnUpdateCheckBox->SetEnabled(version >= ProtocolVersion::VERSION_2_3_0); - // nestedTxModeComboBox->SetEnabled(version >= ProtocolVersion::VERSION_2_5_0); - - // break; - //} - case ChildId::TLS_CHECK_BOX: { tlsCheckBox->SetChecked(!tlsCheckBox->IsChecked()); @@ -551,21 +365,9 @@ namespace ignite break; } - //case ChildId::SSL_MODE_COMBO_BOX: //-AL- may need to remove this later - //{ - // using ssl::SslMode; - - // std::string sslModeStr; - // sslModeComboBox->GetText(sslModeStr); - - // SslMode::Type sslMode = SslMode::FromString(sslModeStr, SslMode::DISABLE); - // sslKeyFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - // sslCertFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - // sslCaFileEdit->SetEnabled(sslMode != SslMode::DISABLE); - - // break; - //} + break; + } default: return false; @@ -673,28 +475,6 @@ namespace ignite cfg.SetTlsAllowInvalidHostnames(tlsAllowInvalidHostnames); cfg.SetTlsCaFile(tlsCaStr); - //std::string sslModeStr; - //std::string sslKeyStr; - //std::string sslCertStr; - //std::string sslCaStr; - - ////sslModeComboBox->GetText(sslModeStr); - ////sslKeyFileEdit->GetText(sslKeyStr); - ////sslCertFileEdit->GetText(sslCertStr); - ////sslCaFileEdit->GetText(sslCaStr); - - //LOG_MSG("Retrieving arguments:"); - //LOG_MSG("SSL Mode: " << sslModeStr); - //LOG_MSG("SSL Key: " << sslKeyStr); - //LOG_MSG("SSL Certificate: " << sslCertStr); - //LOG_MSG("SSL CA: " << sslCaStr); - - //ssl::SslMode::Type sslMode = ssl::SslMode::FromString(sslModeStr, ssl::SslMode::DISABLE); - - //cfg.SetSslMode(sslMode); - //cfg.SetSslKeyFile(sslKeyStr); - //cfg.SetSslCertFile(sslCertStr); - //cfg.SetTlsCaFile(sslCaStr); } void DsnConfigurationWindow::RetrieveAdditionalParameters(config::Configuration& cfg) const @@ -726,53 +506,17 @@ namespace ignite if (fetchSize <= 0) fetchSize = config.GetFetchSize(); - //std::string pageSizeStr; - - //pageSizeEdit->GetText(pageSizeStr); - - //int32_t pageSize = common::LexicalCast(pageSizeStr); - - //if (pageSize <= 0) - // pageSize = config.GetPageSize(); - - //std::string nestedTxModeStr; - - //nestedTxModeComboBox->GetText(nestedTxModeStr); - - // unnecessary code is commented out -AL- - //NestedTxMode::Type mode = NestedTxMode::FromString(nestedTxModeStr, config.GetNestedTxMode()); - - //bool distributedJoins = distributedJoinsCheckBox->IsChecked(); - //bool enforceJoinOrder = enforceJoinOrderCheckBox->IsChecked(); - //bool replicatedOnly = replicatedOnlyCheckBox->IsChecked(); - //bool collocated = collocatedCheckBox->IsChecked(); - //bool lazy = lazyCheckBox->IsChecked(); - //bool skipReducerOnUpdate = skipReducerOnUpdateCheckBox->IsChecked(); - LOG_MSG("Retrieving arguments:"); - LOG_MSG("App name: " << appNameStr); - LOG_MSG("Login timeout (seconds): " << loginTimeoutSecStr); - LOG_MSG("Read preference: " << readPreferenceStr); - LOG_MSG("Fetch size: " << fetchSize); - //LOG_MSG("Nested TX Mode: " << NestedTxMode::ToString(mode)); - //LOG_MSG("Distributed Joins: " << (distributedJoins ? "true" : "false")); - //LOG_MSG("Enforce Join Order: " << (enforceJoinOrder ? "true" : "false")); - //LOG_MSG("Replicated only: " << (replicatedOnly ? "true" : "false")); - //LOG_MSG("Collocated: " << (collocated ? "true" : "false")); - //LOG_MSG("Lazy: " << (lazy ? "true" : "false")); - //LOG_MSG("Skip reducer on update: " << (skipReducerOnUpdate ? "true" : "false")); + LOG_MSG("App name: " << appNameStr); + LOG_MSG("Login timeout (seconds): " << loginTimeoutSecStr); + LOG_MSG("Read preference: " << readPreferenceStr); + LOG_MSG("Fetch size: " << fetchSize); cfg.SetApplicationName(appNameStr); cfg.SetLoginTimeoutSeconds(loginTimeoutSec); cfg.SetReadPreference(readPreferenceStr); cfg.SetFetchSize(fetchSize); - //cfg.SetNestedTxMode(mode); - //cfg.SetDistributedJoins(distributedJoins); - //cfg.SetEnforceJoinOrder(enforceJoinOrder); - //cfg.SetReplicatedOnly(replicatedOnly); - //cfg.SetCollocated(collocated); - //cfg.SetLazy(lazy); - //cfg.SetSkipReducerOnUpdate(skipReducerOnUpdate); + } } } From 7e5288d303a5c4453477e3dc92fd8ab52a134155 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 19 Jan 2022 16:23:53 -0800 Subject: [PATCH 021/165] [AD-522] Implement replicaSet and retryReads on Configuration Window --- .../odbc/system/ui/dsn_configuration_window.h | 15 ++++++++-- .../system/ui/dsn_configuration_window.cpp | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 27df1d8ba..ad8c45e99 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -57,6 +57,9 @@ namespace ignite LOGIN_TIMEOUT_SEC_LABEL, READ_PREFERENCE_EDIT, READ_PREFERENCE_LABEL, + REPLICA_SET_EDIT, + REPLICA_SET_LABEL, + RETRY_READS_CHECK_BOX, FETCH_SIZE_EDIT, FETCH_SIZE_LABEL, PROTOCOL_VERSION_LABEL, @@ -256,12 +259,20 @@ namespace ignite /** Read preference label. */ std::auto_ptr readPreferenceLabel; + /** Replica Set edit. */ + std::auto_ptr< Window > replicaSetEdit; - ///** Enforce join order CheckBox. */ - //std::auto_ptr enforceJoinOrderCheckBox; + /** Replica Set label. */ + std::auto_ptr< Window > replicaSetLabel; + /** Retry reads CheckBox. */ + std::auto_ptr retryReadsCheckBox; + /** Fetch size edit. */ + std::auto_ptr fetchSizeEdit; + /** Fetch size label. */ + std::auto_ptr fetchSizeLabel; /** Protocol version edit field. */ std::auto_ptr protocolVersionLabel; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index fe7e0239b..9a9f7e66d 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -52,6 +52,9 @@ namespace ignite appNameEdit(), readPreferenceLabel(), readPreferenceEdit(), + replicaSetLabel(), + replicaSetEdit(), + retryReadsCheckBox(), fetchSizeLabel(), fetchSizeEdit(), protocolVersionLabel(), @@ -299,6 +302,20 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; + val = config.GetReplicaSet().c_str(); + + replicaSetLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Replica Set:", ChildId::REPLICA_SET_LABEL); + replicaSetEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, + ChildId::REPLICA_SET_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + retryReadsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, + "Retry Reads", ChildId::RETRY_READS_CHECK_BOX, config.IsRetryReads()); + + rowPos += INTERVAL + ROW_HEIGHT; + tmp = common::LexicalCast(config.GetFetchSize()); val = tmp.c_str(); fetchSizeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, @@ -365,6 +382,9 @@ namespace ignite break; } + case ChildId::RETRY_READS_CHECK_BOX: + { + retryReadsCheckBox->SetChecked(!retryReadsCheckBox->IsChecked()); break; } @@ -482,9 +502,13 @@ namespace ignite std::string appNameStr; std::string readPreferenceStr; + std::string replicaSetStr; appNameEdit->GetText(appNameStr); readPreferenceEdit->GetText(readPreferenceStr); + replicaSetEdit->GetText(replicaSetStr); + + bool retryReads = retryReadsCheckBox->IsChecked(); std::string loginTimeoutSecStr; @@ -510,11 +534,15 @@ namespace ignite LOG_MSG("App name: " << appNameStr); LOG_MSG("Login timeout (seconds): " << loginTimeoutSecStr); LOG_MSG("Read preference: " << readPreferenceStr); + LOG_MSG("Replica Set: " << replicaSetStr); + LOG_MSG("Retry reads: " << (retryReads ? "true" : "false")); LOG_MSG("Fetch size: " << fetchSize); cfg.SetApplicationName(appNameStr); cfg.SetLoginTimeoutSeconds(loginTimeoutSec); cfg.SetReadPreference(readPreferenceStr); + cfg.SetReplicaSet(replicaSetStr); + cfg.SetRetryReads(retryReads); cfg.SetFetchSize(fetchSize); } From 27b72e14aefae42457d579961ae734d2c4fdb789 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Wed, 19 Jan 2022 17:08:11 -0800 Subject: [PATCH 022/165] [AD-517] Re-enable unit tests - WIP - still need to cleanup --- src/odbc-test/CMakeLists.txt | 43 +- src/odbc-test/CMakeLists.txt.bak | 113 +++++ src/odbc-test/src/configuration_test.cpp | 469 +++++++++++------- .../ignite/odbc/config/configuration.h | 42 +- .../system/ui/dsn_configuration_window.cpp | 4 +- src/odbc/src/config/configuration.cpp | 26 +- .../src/config/connection_string_parser.cpp | 38 +- src/odbc/src/connection.cpp | 11 +- src/odbc/src/dsn_config.cpp | 11 - 9 files changed, 458 insertions(+), 299 deletions(-) create mode 100644 src/odbc-test/CMakeLists.txt.bak diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 11aa3a60c..ae4ab2274 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -32,6 +32,7 @@ include_directories(include ../odbc/include ../network/include) set(SOURCES src/dummy_test.cpp + src/configuration_test.cpp # TODO uncomment/rework the tests after get some connectivity and functionalities working. # src/teamcity/teamcity_boost.cpp # src/teamcity/teamcity_messages.cpp @@ -71,27 +72,27 @@ set(SOURCES # src/streaming_test.cpp # src/cursor_binding_test.cpp # src/test_server.cpp -# ../odbc/src/log.cpp -# ../odbc/src/cursor.cpp -# ../odbc/src/diagnostic/diagnostic_record.cpp -# ../odbc/src/diagnostic/diagnostic_record_storage.cpp -# ../odbc/src/config/config_tools.cpp -# ../odbc/src/config/configuration.cpp -# ../odbc/src/config/connection_info.cpp -# ../odbc/src/config/connection_string_parser.cpp -# ../odbc/src/app/application_data_buffer.cpp -# ../odbc/src/ssl_mode.cpp -# ../odbc/src/sql/sql_parser.cpp -# ../odbc/src/sql/sql_lexer.cpp -# ../odbc/src/sql/sql_set_streaming_command.cpp -# ../odbc/src/sql/sql_utils.cpp -# ../odbc/src/row.cpp -# ../odbc/src/protocol_version.cpp -# ../odbc/src/column.cpp -# ../odbc/src/common_types.cpp -# ../odbc/src/utility.cpp -# ../odbc/src/result_page.cpp -# ../odbc/src/nested_tx_mode.cpp + ../odbc/src/log.cpp + ../odbc/src/cursor.cpp + ../odbc/src/diagnostic/diagnostic_record.cpp + ../odbc/src/diagnostic/diagnostic_record_storage.cpp + ../odbc/src/config/config_tools.cpp + ../odbc/src/config/configuration.cpp + ../odbc/src/config/connection_info.cpp + ../odbc/src/config/connection_string_parser.cpp + ../odbc/src/app/application_data_buffer.cpp + ../odbc/src/ssl_mode.cpp + ../odbc/src/sql/sql_parser.cpp + ../odbc/src/sql/sql_lexer.cpp + ../odbc/src/sql/sql_set_streaming_command.cpp + ../odbc/src/sql/sql_utils.cpp + ../odbc/src/row.cpp + ../odbc/src/protocol_version.cpp + ../odbc/src/column.cpp + ../odbc/src/common_types.cpp + ../odbc/src/utility.cpp + ../odbc/src/result_page.cpp + ../odbc/src/nested_tx_mode.cpp ) add_executable(${TARGET} ${SOURCES}) diff --git a/src/odbc-test/CMakeLists.txt.bak b/src/odbc-test/CMakeLists.txt.bak new file mode 100644 index 000000000..0d30d5356 --- /dev/null +++ b/src/odbc-test/CMakeLists.txt.bak @@ -0,0 +1,113 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +project(ignite-odbc-tests) + +set(TARGET ${PROJECT_NAME}) + +if (WIN32) + set(Boost_USE_STATIC_LIBS ON) +endif() + +find_package(Boost 1.53 REQUIRED COMPONENTS unit_test_framework chrono thread system regex) + +find_package(ODBC REQUIRED) + +include_directories(SYSTEM ${ODBC_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${JNI_INCLUDE_DIRS}) +include_directories(include ../odbc/include ../network/include) + +set(SOURCES + src/dummy_test.cpp + src/configuration_test.cpp +# TODO uncomment/rework the tests after get some connectivity and functionalities working. +# src/teamcity/teamcity_boost.cpp +# src/teamcity/teamcity_messages.cpp +# src/parser_test.cpp +# src/cursor_test.cpp +# src/connection_info_test.cpp +# src/connection_test.cpp +# src/application_data_buffer_test.cpp +# src/column_test.cpp +# src/configuration_test.cpp +# src/row_test.cpp +# src/meta_queries_test.cpp +# src/utility_test.cpp +# src/queries_test.cpp +# src/queries_ssl_test.cpp +# src/test_utils.cpp +# src/sql_test_suite_fixture.cpp +# src/sql_string_functions_test.cpp +# src/sql_numeric_functions_test.cpp +# src/sql_aggregate_functions_test.cpp +# src/sql_system_functions_test.cpp +# src/sql_esc_convert_function_test.cpp +# src/sql_operators_test.cpp +# src/sql_value_expressions_test.cpp +# src/sql_types_test.cpp +# src/sql_date_time_functions_test.cpp +# src/sql_outer_join_test.cpp +# src/sql_get_info_test.cpp +# src/api_robustness_test.cpp +# src/attributes_test.cpp +# src/errors_test.cpp +# src/odbc_test_suite.cpp +# src/types_test.cpp +# src/transaction_test.cpp +# src/authentication_test.cpp +# src/sql_parsing_test.cpp +# src/streaming_test.cpp +# src/cursor_binding_test.cpp +# src/test_server.cpp +# ../odbc/src/log.cpp +# ../odbc/src/cursor.cpp +# ../odbc/src/diagnostic/diagnostic_record.cpp +# ../odbc/src/diagnostic/diagnostic_record_storage.cpp +# ../odbc/src/config/config_tools.cpp +# ../odbc/src/config/configuration.cpp +# ../odbc/src/config/connection_info.cpp +# ../odbc/src/config/connection_string_parser.cpp +# ../odbc/src/app/application_data_buffer.cpp +# ../odbc/src/ssl_mode.cpp +# ../odbc/src/sql/sql_parser.cpp +# ../odbc/src/sql/sql_lexer.cpp +# ../odbc/src/sql/sql_set_streaming_command.cpp +# ../odbc/src/sql/sql_utils.cpp +# ../odbc/src/row.cpp +# ../odbc/src/protocol_version.cpp +# ../odbc/src/column.cpp +# ../odbc/src/common_types.cpp +# ../odbc/src/utility.cpp +# ../odbc/src/result_page.cpp +# ../odbc/src/nested_tx_mode.cpp + ) + +add_executable(${TARGET} ${SOURCES}) + +target_link_libraries(${TARGET} ${Boost_LIBRARIES} ignite ${ODBC_LIBRARY}) +target_code_coverage(${TARGET} PUBLIC AUTO ALL) + +if (WIN32) + remove_definitions(-DUNICODE=1) +else() + add_definitions(-DBOOST_TEST_DYN_LINK) +endif() + +set(TEST_TARGET IgniteOdbcTest) + +add_test(NAME ${TEST_TARGET} COMMAND ${TARGET} --catch_system_errors=no --log_level=all) + +set_tests_properties(${TEST_TARGET} PROPERTIES ENVIRONMENT IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH=${PROJECT_SOURCE_DIR}/config) diff --git a/src/odbc-test/src/configuration_test.cpp b/src/odbc-test/src/configuration_test.cpp index b6f793def..9d21d1f60 100644 --- a/src/odbc-test/src/configuration_test.cpp +++ b/src/odbc-test/src/configuration_test.cpp @@ -32,22 +32,34 @@ using namespace ignite::odbc::config; namespace { - const std::string testDriverName = "Ignite Driver"; - const std::string testServerHost = "testhost.com"; - const uint16_t testServerPort = 4242; - const std::string testSchemaName = "TestSchema"; - const std::string testDsn = "Ignite DSN"; - const int32_t testPageSize = 4321; - const bool testDistributedJoins = true; - const bool testEnforceJoinOrder = true; - const bool testReplicatedOnly = true; - const bool testCollocated = true; - const bool testLazy = true; - const bool testSkipReducerOnUpdate = true; - - const std::string testAddressStr = testServerHost + ':' + ignite::common::LexicalCast(testServerPort); - - const EndPoint testAddress(testServerHost, testServerPort, 10); + const std::string testDriverName = "Test Driver"; + const std::string testDsn = "Test DSN"; + const std::string testHostname = "testhost.com"; + const uint16_t testServerPort = 27019; + const std::string testDatabaseName = "testDatabase"; + const std::string testUsername = "testUser"; + const std::string testPassword = "testPassword"; + const std::string testAppName = "testAppName"; + const int32_t testLoginTimeoutSec = 3000; + const std::string testReadPreference = "primaryPreferred"; + const std::string testReplicaSet = "rs0"; + const bool testRetryReads = false; + const bool testTlsFlag = false; + const bool testTlsAllowInvalidHostnamesFlag = true; + const std::string testTlsCaFile = "/path/to/cafile"; + const std::string testSshUser = "testEc2User"; + const std::string testSshHost = "testsshhost.com"; + const std::string testSshPrivateKeyFile = "/path/to/keyfile"; + const std::string testSshPrivateKeyPassphrase = "testPassphrase"; + const bool testSshStrictHostKeyCheckingFlag = false; + const std::string testSshKnownHostsFile = "/path/to/knownhostsfile"; + const std::string testScanMethod = "idForward"; + const int32_t testScanLimit = 3000; + const std::string testSchemaName = "testSchemaName"; + const bool testRefreshSchemaFlag = true; + const int32_t testDefaultFetchSize = 4321; + + const EndPoint testAddress(testHostname, testServerPort, 10); } const char* BoolToStr(bool val, bool lowerCase = true) @@ -99,28 +111,8 @@ void CheckValidAddress(const char* connectStr, const EndPoint& endPoint) ParseValidConnectString(connectStr, cfg); - const std::vector& addrs = cfg.GetAddresses(); - - BOOST_REQUIRE_EQUAL(addrs.size(), 1); - BOOST_CHECK_EQUAL(addrs[0].host, endPoint.host); - BOOST_CHECK_EQUAL(addrs[0].port, endPoint.port); -} - -void CheckValidAddresses(const char* connectStr, const std::vector& endPoints) -{ - Configuration cfg; - - ParseValidConnectString(connectStr, cfg); - - const std::vector& addrs = cfg.GetAddresses(); - - BOOST_REQUIRE_EQUAL(addrs.size(), endPoints.size()); - - for (size_t i = 0; i < addrs.size(); ++i) - { - BOOST_CHECK_EQUAL(addrs[i].host, endPoints[i].host); - BOOST_CHECK_EQUAL(addrs[i].port, endPoints[i].port); - } + BOOST_CHECK_EQUAL(cfg.GetHostname(), endPoint.host); + BOOST_CHECK_EQUAL(cfg.GetTcpPort(), endPoint.port); } void CheckValidProtocolVersion(const char* connectStr, ProtocolVersion version) @@ -129,7 +121,7 @@ void CheckValidProtocolVersion(const char* connectStr, ProtocolVersion version) ParseValidConnectString(connectStr, cfg); - BOOST_CHECK(cfg.GetProtocolVersion() == version); + //BOOST_CHECK(cfg.GetProtocolVersion() == version); } void CheckSupportedProtocolVersion(const char* connectStr) @@ -138,7 +130,7 @@ void CheckSupportedProtocolVersion(const char* connectStr) ParseValidConnectString(connectStr, cfg); - BOOST_CHECK(cfg.GetProtocolVersion().IsSupported()); + //BOOST_CHECK(cfg.GetProtocolVersion().IsSupported()); } void CheckInvalidProtocolVersion(const char* connectStr) @@ -147,7 +139,7 @@ void CheckInvalidProtocolVersion(const char* connectStr) ParseConnectStringWithError(connectStr, cfg); - BOOST_CHECK(cfg.GetProtocolVersion() == Configuration::DefaultValue::protocolVersion); + //BOOST_CHECK(cfg.GetProtocolVersion() == Configuration::DefaultValue::protocolVersion); } void CheckValidBoolValue(const std::string& connectStr, const std::string& key, bool val) @@ -179,39 +171,60 @@ void CheckInvalidBoolValue(const std::string& connectStr, const std::string& key void CheckConnectionConfig(const Configuration& cfg) { BOOST_CHECK_EQUAL(cfg.GetDriver(), testDriverName); - BOOST_CHECK_EQUAL(cfg.GetSchema(), testSchemaName); - BOOST_CHECK_EQUAL(cfg.GetPageSize(), testPageSize); - BOOST_CHECK_EQUAL(cfg.IsDistributedJoins(), testDistributedJoins); - BOOST_CHECK_EQUAL(cfg.IsEnforceJoinOrder(), testEnforceJoinOrder); - BOOST_CHECK_EQUAL(cfg.IsReplicatedOnly(), testReplicatedOnly); - BOOST_CHECK_EQUAL(cfg.IsCollocated(), testCollocated); - BOOST_CHECK_EQUAL(cfg.IsLazy(), testLazy); - BOOST_CHECK_EQUAL(cfg.IsSkipReducerOnUpdate(), testSkipReducerOnUpdate); + BOOST_CHECK_EQUAL(cfg.GetDatabase(), testDatabaseName); + BOOST_CHECK_EQUAL(cfg.GetHostname(), testHostname); + BOOST_CHECK_EQUAL(cfg.GetTcpPort(), testServerPort); + BOOST_CHECK_EQUAL(cfg.GetUser(), testUsername); + BOOST_CHECK_EQUAL(cfg.GetPassword(), testPassword); + BOOST_CHECK_EQUAL(cfg.GetApplicationName(), testAppName); + BOOST_CHECK_EQUAL(cfg.GetLoginTimeoutSeconds(), testLoginTimeoutSec); + BOOST_CHECK_EQUAL(cfg.GetReadPreference(), testReadPreference); + BOOST_CHECK_EQUAL(cfg.GetReplicaSet(), testReplicaSet); + BOOST_CHECK_EQUAL(cfg.IsRetryReads(), testRetryReads); + BOOST_CHECK_EQUAL(cfg.IsTls(), testTlsFlag); + BOOST_CHECK_EQUAL(cfg.IsTlsAllowInvalidHostnames(), testTlsAllowInvalidHostnamesFlag); + BOOST_CHECK_EQUAL(cfg.GetTlsCaFile(), testTlsCaFile); + BOOST_CHECK_EQUAL(cfg.GetSshUser(), testSshUser); + BOOST_CHECK_EQUAL(cfg.GetSshHost(), testSshHost); + BOOST_CHECK_EQUAL(cfg.GetSshPrivateKeyFile(), testSshPrivateKeyFile); + BOOST_CHECK_EQUAL(cfg.GetSshPrivateKeyPassphrase(), testSshPrivateKeyPassphrase); + BOOST_CHECK_EQUAL(cfg.IsSshStrictHostKeyChecking(), testSshStrictHostKeyCheckingFlag); + BOOST_CHECK_EQUAL(cfg.GetSshKnownHostsFile(), testSshKnownHostsFile); + BOOST_CHECK_EQUAL(cfg.GetScanMethod(), testScanMethod); + BOOST_CHECK_EQUAL(cfg.GetScanLimit(), testScanLimit); + BOOST_CHECK_EQUAL(cfg.GetSchemaName(), testSchemaName); + BOOST_CHECK_EQUAL(cfg.IsSchemaRefresh(), testRefreshSchemaFlag); + BOOST_CHECK_EQUAL(cfg.GetDefaultFetchSize(), testDefaultFetchSize); BOOST_CHECK(!cfg.IsDsnSet()); - BOOST_CHECK(!cfg.IsHostSet()); - BOOST_CHECK(!cfg.IsTcpPortSet()); - - BOOST_CHECK(cfg.IsAddressesSet()); - - const std::vector& addrs = cfg.GetAddresses(); - - BOOST_REQUIRE(!addrs.empty()); - BOOST_CHECK_EQUAL(addrs[0].host, testAddress.host); - BOOST_CHECK_EQUAL(addrs[0].port, testAddress.port); std::stringstream constructor; - constructor << "address=" << testAddressStr << ';' - << "collocated=" << BoolToStr(testCollocated) << ';' - << "distributed_joins=" << BoolToStr(testDistributedJoins) << ';' + constructor << "app_name=" << testAppName << ';' + << "database=" << testDatabaseName << ';' + << "default_fetch_size=" << testDefaultFetchSize << ';' << "driver={" << testDriverName << "};" - << "enforce_join_order=" << BoolToStr(testEnforceJoinOrder) << ';' - << "lazy=" << BoolToStr(testLazy) << ';' - << "page_size=" << testPageSize << ';' - << "replicated_only=" << BoolToStr(testReplicatedOnly) << ';' - << "schema=" << testSchemaName << ';' - << "skip_reducer_on_update=" << BoolToStr(testReplicatedOnly) << ';'; + << "hostname=" << testHostname << ';' + << "login_timeout_sec=" << testLoginTimeoutSec << ';' + << "password=" << testPassword << ';' + << "port=" << testServerPort << ';' + << "read_preference=" << testReadPreference << ';' + << "refresh_schema=" << BoolToStr(testRefreshSchemaFlag) << ';' + << "replica_set=" << testReplicaSet << ';' + << "retry_reads=" << BoolToStr(testRetryReads) << ';' + << "scan_limit=" << testScanLimit << ';' + << "scan_method=" << testScanMethod << ';' + << "schema_name=" << testSchemaName << ';' + << "ssh_host=" << testSshHost << ';' + << "ssh_known_hosts_file=" << testSshKnownHostsFile << ';' + << "ssh_private_key_file=" << testSshPrivateKeyFile << ';' + << "ssh_private_key_passphrase=" << testSshPrivateKeyPassphrase << ';' + << "ssh_strict_host_key_checking=" << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' + << "ssh_user=" << testSshUser << ';' + << "tls=" << BoolToStr(testTlsFlag) << ';' + << "tls_allow_invalid_hostnames=" << BoolToStr(testTlsAllowInvalidHostnamesFlag) << ';' + << "tls_ca_file=" << testTlsCaFile << ';' + << "user=" << testUsername << ';'; const std::string& expectedStr = constructor.str(); @@ -222,35 +235,62 @@ void CheckDsnConfig(const Configuration& cfg) { BOOST_CHECK_EQUAL(cfg.GetDriver(), testDriverName); BOOST_CHECK_EQUAL(cfg.GetDsn(), testDsn); - BOOST_CHECK_EQUAL(cfg.GetSchema(), Configuration::DefaultValue::schema); - BOOST_CHECK_EQUAL(cfg.GetHost(), std::string()); + BOOST_CHECK_EQUAL(cfg.GetDatabase(), Configuration::DefaultValue::database); + BOOST_CHECK_EQUAL(cfg.GetHostname(), Configuration::DefaultValue::hostname); BOOST_CHECK_EQUAL(cfg.GetTcpPort(), Configuration::DefaultValue::port); - BOOST_CHECK_EQUAL(cfg.GetPageSize(), Configuration::DefaultValue::pageSize); - BOOST_CHECK_EQUAL(cfg.IsDistributedJoins(), false); - BOOST_CHECK_EQUAL(cfg.IsEnforceJoinOrder(), false); - BOOST_CHECK_EQUAL(cfg.IsReplicatedOnly(), false); - BOOST_CHECK_EQUAL(cfg.IsCollocated(), false); - BOOST_CHECK_EQUAL(cfg.IsLazy(), false); - BOOST_CHECK_EQUAL(cfg.IsSkipReducerOnUpdate(), false); - BOOST_CHECK(cfg.GetAddresses().empty()); + BOOST_CHECK_EQUAL(cfg.GetUser(), Configuration::DefaultValue::user); + BOOST_CHECK_EQUAL(cfg.GetPassword(), Configuration::DefaultValue::password); + BOOST_CHECK_EQUAL(cfg.GetApplicationName(), Configuration::DefaultValue::appName); + BOOST_CHECK_EQUAL(cfg.GetLoginTimeoutSeconds(), Configuration::DefaultValue::loginTimeoutSec); + BOOST_CHECK_EQUAL(cfg.GetReadPreference(), Configuration::DefaultValue::readPreference); + BOOST_CHECK_EQUAL(cfg.GetReplicaSet(), Configuration::DefaultValue::replicaSet); + BOOST_CHECK_EQUAL(cfg.IsRetryReads(), Configuration::DefaultValue::retryReads); + BOOST_CHECK_EQUAL(cfg.IsTls(), Configuration::DefaultValue::tls); + BOOST_CHECK_EQUAL(cfg.IsTlsAllowInvalidHostnames(), Configuration::DefaultValue::tlsAllowInvalidHostnames); + BOOST_CHECK_EQUAL(cfg.GetTlsCaFile(), Configuration::DefaultValue::tlsCaFile); + BOOST_CHECK_EQUAL(cfg.GetSshUser(), Configuration::DefaultValue::sshUser); + BOOST_CHECK_EQUAL(cfg.GetSshHost(), Configuration::DefaultValue::sshHost); + BOOST_CHECK_EQUAL(cfg.GetSshPrivateKeyFile(), Configuration::DefaultValue::sshPrivateKeyFile); + BOOST_CHECK_EQUAL(cfg.GetSshPrivateKeyPassphrase(), Configuration::DefaultValue::sshPrivateKeyPassphrase); + BOOST_CHECK_EQUAL(cfg.IsSshStrictHostKeyChecking(), Configuration::DefaultValue::sshStrictHostKeyChecking); + BOOST_CHECK_EQUAL(cfg.GetSshKnownHostsFile(), Configuration::DefaultValue::sshKnownHostsFile); + BOOST_CHECK_EQUAL(cfg.GetScanMethod(), Configuration::DefaultValue::scanMethod); + BOOST_CHECK_EQUAL(cfg.GetScanLimit(), Configuration::DefaultValue::scanLimit); + BOOST_CHECK_EQUAL(cfg.GetSchemaName(), Configuration::DefaultValue::schemaName); + BOOST_CHECK_EQUAL(cfg.IsSchemaRefresh(), Configuration::DefaultValue::refreshSchema); + BOOST_CHECK_EQUAL(cfg.GetDefaultFetchSize(), Configuration::DefaultValue::defaultFetchSize); } BOOST_AUTO_TEST_SUITE(ConfigurationTestSuite) -BOOST_AUTO_TEST_CASE(CheckTestValuesNotEquealDefault) +BOOST_AUTO_TEST_CASE(CheckTestValuesNotEqualDefault) { BOOST_CHECK_NE(testDriverName, Configuration::DefaultValue::driver); - BOOST_CHECK_NE(testAddressStr, Configuration::DefaultValue::address); - BOOST_CHECK_NE(testServerPort, Configuration::DefaultValue::port); - BOOST_CHECK_NE(testSchemaName, Configuration::DefaultValue::schema); BOOST_CHECK_NE(testDsn, Configuration::DefaultValue::dsn); - BOOST_CHECK_NE(testPageSize, Configuration::DefaultValue::pageSize); - BOOST_CHECK_NE(testDistributedJoins, Configuration::DefaultValue::distributedJoins); - BOOST_CHECK_NE(testEnforceJoinOrder, Configuration::DefaultValue::enforceJoinOrder); - BOOST_CHECK_NE(testReplicatedOnly, Configuration::DefaultValue::replicatedOnly); - BOOST_CHECK_NE(testCollocated, Configuration::DefaultValue::collocated); - BOOST_CHECK_NE(testLazy, Configuration::DefaultValue::lazy); - BOOST_CHECK_NE(testSkipReducerOnUpdate, Configuration::DefaultValue::skipReducerOnUpdate); + BOOST_CHECK_NE(testDatabaseName, Configuration::DefaultValue::database); + BOOST_CHECK_NE(testHostname, Configuration::DefaultValue::hostname); + BOOST_CHECK_NE(testServerPort, Configuration::DefaultValue::port); + BOOST_CHECK_NE(testUsername, Configuration::DefaultValue::user); + BOOST_CHECK_NE(testPassword, Configuration::DefaultValue::password); + BOOST_CHECK_NE(testAppName, Configuration::DefaultValue::appName); + BOOST_CHECK_NE(testLoginTimeoutSec, Configuration::DefaultValue::loginTimeoutSec); + BOOST_CHECK_NE(testReadPreference, Configuration::DefaultValue::readPreference); + BOOST_CHECK_NE(testReplicaSet, Configuration::DefaultValue::replicaSet); + BOOST_CHECK_NE(testRetryReads, Configuration::DefaultValue::retryReads); + BOOST_CHECK_NE(testTlsFlag, Configuration::DefaultValue::tls); + BOOST_CHECK_NE(testTlsAllowInvalidHostnamesFlag, Configuration::DefaultValue::tlsAllowInvalidHostnames); + BOOST_CHECK_NE(testTlsCaFile, Configuration::DefaultValue::tlsCaFile); + BOOST_CHECK_NE(testSshUser, Configuration::DefaultValue::sshUser); + BOOST_CHECK_NE(testSshHost, Configuration::DefaultValue::sshHost); + BOOST_CHECK_NE(testSshPrivateKeyFile, Configuration::DefaultValue::sshPrivateKeyFile); + BOOST_CHECK_NE(testSshPrivateKeyPassphrase, Configuration::DefaultValue::sshPrivateKeyPassphrase); + BOOST_CHECK_NE(testSshStrictHostKeyCheckingFlag, Configuration::DefaultValue::sshStrictHostKeyChecking); + BOOST_CHECK_NE(testSshKnownHostsFile, Configuration::DefaultValue::sshKnownHostsFile); + BOOST_CHECK_NE(testScanMethod, Configuration::DefaultValue::scanMethod); + BOOST_CHECK_NE(testScanLimit, Configuration::DefaultValue::scanLimit); + BOOST_CHECK_NE(testSchemaName, Configuration::DefaultValue::schemaName); + BOOST_CHECK_NE(testRefreshSchemaFlag, Configuration::DefaultValue::refreshSchema); + BOOST_CHECK_NE(testDefaultFetchSize, Configuration::DefaultValue::defaultFetchSize); } BOOST_AUTO_TEST_CASE(TestConnectStringUppercase) @@ -259,16 +299,31 @@ BOOST_AUTO_TEST_CASE(TestConnectStringUppercase) std::stringstream constructor; - constructor << "DRIVER={" << testDriverName << "};" - << "LAZY=" << BoolToStr(testLazy, false) << ';' - << "ADDRESS=" << testAddressStr << ';' - << "DISTRIBUTED_JOINS=" << BoolToStr(testDistributedJoins, false) << ';' - << "ENFORCE_JOIN_ORDER=" << BoolToStr(testEnforceJoinOrder, false) << ';' - << "COLLOCATED=" << BoolToStr(testCollocated, false) << ';' - << "REPLICATED_ONLY=" << BoolToStr(testReplicatedOnly, false) << ';' - << "PAGE_SIZE=" << testPageSize << ';' - << "SCHEMA=" << testSchemaName << ';' - << "SKIP_REDUCER_ON_UPDATE=" << BoolToStr(testSkipReducerOnUpdate, false); + constructor << "HOSTNAME=" << testHostname << ';' + << "PORT=" << testServerPort << ';' + << "DATABASE=" << testDatabaseName << ';' + << "USER=" << testUsername << ';' + << "PASSWORD=" << testPassword << ';' + << "APP_NAME=" << testAppName << ';' + << "LOGIN_TIMEOUT_SEC=" << testLoginTimeoutSec << ';' + << "READ_PREFERENCE=" << testReadPreference << ';' + << "REPLICA_SET=" << testReplicaSet << ';' + << "RETRY_READS=" << BoolToStr(testRetryReads) << ';' + << "TLS=" << BoolToStr(testTlsFlag) << ';' + << "TLS_ALLOW_INVALID_HOSTNAMES=" << BoolToStr(testTlsAllowInvalidHostnamesFlag) << ';' + << "TLS_CA_FILE=" << testTlsCaFile << ';' + << "SSH_USER=" << testSshUser << ';' + << "SSH_HOST=" << testSshHost << ';' + << "SSH_PRIVATE_KEY_FILE=" << testSshPrivateKeyFile << ';' + << "SSH_PRIVATE_KEY_PASSPHRASE=" << testSshPrivateKeyPassphrase << ';' + << "SSH_STRICT_HOST_KEY_CHECKING=" << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' + << "SSH_KNOWN_HOSTS_FILE=" << testSshKnownHostsFile << ';' + << "SCAN_METHOD=" << testScanMethod << ';' + << "SCAN_LIMIT=" << testScanLimit << ';' + << "SCHEMA_NAME=" << testSchemaName << ';' + << "REFRESH_SCHEMA=" << BoolToStr(testRefreshSchemaFlag) << ';' + << "DEFAULT_FETCH_SIZE=" << testDefaultFetchSize << ';' + << "DRIVER={" << testDriverName << "};"; const std::string& connectStr = constructor.str(); @@ -283,16 +338,31 @@ BOOST_AUTO_TEST_CASE(TestConnectStringLowercase) std::stringstream constructor; - constructor << "driver={" << testDriverName << "};" - << "lazy=" << BoolToStr(testLazy) << ';' - << "address=" << testAddressStr << ';' - << "page_size=" << testPageSize << ';' - << "distributed_joins=" << BoolToStr(testDistributedJoins) << ';' - << "enforce_join_order=" << BoolToStr(testEnforceJoinOrder) << ';' - << "replicated_only=" << BoolToStr(testReplicatedOnly) << ';' - << "collocated=" << BoolToStr(testCollocated) << ';' - << "schema=" << testSchemaName << ';' - << "skip_reducer_on_update=" << BoolToStr(testSkipReducerOnUpdate); + constructor << "hostname=" << testHostname << ';' + << "port=" << testServerPort << ';' + << "database=" << testDatabaseName << ';' + << "user=" << testUsername << ';' + << "password=" << testPassword << ';' + << "app_name=" << testAppName << ';' + << "login_timeout_sec=" << testLoginTimeoutSec << ';' + << "read_preference=" << testReadPreference << ';' + << "replica_set=" << testReplicaSet << ';' + << "retry_reads=" << BoolToStr(testRetryReads) << ';' + << "tls=" << BoolToStr(testTlsFlag) << ';' + << "tls_allow_invalid_hostnames=" << BoolToStr(testTlsAllowInvalidHostnamesFlag) << ';' + << "tls_ca_file=" << testTlsCaFile << ';' + << "ssh_user=" << testSshUser << ';' + << "ssh_host=" << testSshHost << ';' + << "ssh_private_key_file=" << testSshPrivateKeyFile << ';' + << "ssh_private_key_passphrase=" << testSshPrivateKeyPassphrase << ';' + << "ssh_strict_host_key_checking=" << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' + << "ssh_known_hosts_file=" << testSshKnownHostsFile << ';' + << "scan_method=" << testScanMethod << ';' + << "scan_limit=" << testScanLimit << ';' + << "schema_name=" << testSchemaName << ';' + << "refresh_schema=" << BoolToStr(testRefreshSchemaFlag) << ';' + << "default_fetch_size=" << testDefaultFetchSize << ';' + << "driver={" << testDriverName << "};"; const std::string& connectStr = constructor.str(); @@ -307,16 +377,31 @@ BOOST_AUTO_TEST_CASE(TestConnectStringZeroTerminated) std::stringstream constructor; - constructor << "driver={" << testDriverName << "};" - << "address=" << testAddressStr << ';' - << "lazy=" << BoolToStr(testLazy) << ';' - << "page_size=" << testPageSize << ';' - << "replicated_only=" << BoolToStr(testReplicatedOnly) << ';' - << "collocated=" << BoolToStr(testCollocated) << ';' - << "distributed_joins=" << BoolToStr(testDistributedJoins) << ';' - << "enforce_join_order=" << BoolToStr(testEnforceJoinOrder) << ';' - << "schema=" << testSchemaName << ';' - << "skip_reducer_on_update=" << BoolToStr(testSkipReducerOnUpdate); + constructor << "hostname=" << testHostname << ';' + << "port=" << testServerPort << ';' + << "database=" << testDatabaseName << ';' + << "user=" << testUsername << ';' + << "password=" << testPassword << ';' + << "app_name=" << testAppName << ';' + << "login_timeout_sec=" << testLoginTimeoutSec << ';' + << "read_preference=" << testReadPreference << ';' + << "replica_set=" << testReplicaSet << ';' + << "retry_reads=" << BoolToStr(testRetryReads) << ';' + << "tls=" << BoolToStr(testTlsFlag) << ';' + << "tls_allow_invalid_hostnames=" << BoolToStr(testTlsAllowInvalidHostnamesFlag) << ';' + << "tls_ca_file=" << testTlsCaFile << ';' + << "ssh_user=" << testSshUser << ';' + << "ssh_host=" << testSshHost << ';' + << "ssh_private_key_file=" << testSshPrivateKeyFile << ';' + << "ssh_private_key_passphrase=" << testSshPrivateKeyPassphrase << ';' + << "ssh_strict_host_key_checking=" << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' + << "ssh_known_hosts_file=" << testSshKnownHostsFile << ';' + << "scan_method=" << testScanMethod << ';' + << "scan_limit=" << testScanLimit << ';' + << "schema_name=" << testSchemaName << ';' + << "refresh_schema=" << BoolToStr(testRefreshSchemaFlag) << ';' + << "default_fetch_size=" << testDefaultFetchSize << ';' + << "driver={" << testDriverName << "};"; std::string connectStr = constructor.str(); @@ -333,16 +418,31 @@ BOOST_AUTO_TEST_CASE(TestConnectStringMixed) std::stringstream constructor; - constructor << "Driver={" << testDriverName << "};" - << "Lazy=" << BoolToStr(testLazy) << ';' - << "Address=" << testAddressStr << ';' - << "Page_Size=" << testPageSize << ';' - << "Distributed_Joins=" << BoolToStr(testDistributedJoins, false) << ';' - << "Enforce_Join_Order=" << BoolToStr(testEnforceJoinOrder) << ';' - << "Replicated_Only=" << BoolToStr(testReplicatedOnly, false) << ';' - << "Collocated=" << BoolToStr(testCollocated) << ';' - << "Schema=" << testSchemaName << ';' - << "Skip_Reducer_On_Update=" << BoolToStr(testSkipReducerOnUpdate); + constructor << "Hostname=" << testHostname << ';' + << "Port=" << testServerPort << ';' + << "Database=" << testDatabaseName << ';' + << "User=" << testUsername << ';' + << "Password=" << testPassword << ';' + << "App_Name=" << testAppName << ';' + << "Login_Timeout_Sec=" << testLoginTimeoutSec << ';' + << "Read_Preference=" << testReadPreference << ';' + << "Replica_Set=" << testReplicaSet << ';' + << "Retry_Reads=" << BoolToStr(testRetryReads) << ';' + << "Tls=" << BoolToStr(testTlsFlag) << ';' + << "Tls_Allow_Invalid_Hostnames=" << BoolToStr(testTlsAllowInvalidHostnamesFlag) << ';' + << "Tls_Ca_File=" << testTlsCaFile << ';' + << "Ssh_User=" << testSshUser << ';' + << "Ssh_Host=" << testSshHost << ';' + << "Ssh_Private_Key_File=" << testSshPrivateKeyFile << ';' + << "Ssh_Private_Key_Passphrase=" << testSshPrivateKeyPassphrase << ';' + << "Ssh_Strict_Host_Key_Checking=" << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' + << "Ssh_Known_Hosts_File=" << testSshKnownHostsFile << ';' + << "Scan_Method=" << testScanMethod << ';' + << "Scan_Limit=" << testScanLimit << ';' + << "Schema_Name=" << testSchemaName << ';' + << "Refresh_Schema=" << BoolToStr(testRefreshSchemaFlag) << ';' + << "Default_Fetch_Size=" << testDefaultFetchSize << ';' + << "Driver={" << testDriverName << "};"; const std::string& connectStr = constructor.str(); @@ -357,16 +457,31 @@ BOOST_AUTO_TEST_CASE(TestConnectStringWhitepaces) std::stringstream constructor; - constructor << "DRIVER = {" << testDriverName << "} ;\n" - << " ADDRESS =" << testAddressStr << "; " - << " PAGE_SIZE= " << testPageSize << ';' - << " DISTRIBUTED_JOINS=" << BoolToStr(testDistributedJoins, false) << ';' - << "LAZY=" << BoolToStr(testLazy, false) << ';' - << "COLLOCATED =" << BoolToStr(testCollocated, false) << " ;" - << " REPLICATED_ONLY= " << BoolToStr(testReplicatedOnly, false) << ';' - << "ENFORCE_JOIN_ORDER= " << BoolToStr(testEnforceJoinOrder, false) << " ;" - << "SCHEMA = \n\r" << testSchemaName << ';' - << " skip_reducer_on_update=" << BoolToStr(testSkipReducerOnUpdate, false); + constructor << " HOSTNAME=" << testHostname << ';' + << "PORT =" << testServerPort << ';' + << " DATABASE=" << testDatabaseName << ';' + << "USER =" << testUsername << ';' + << "PASSWORD=" << testPassword << ';' + << "APP_NAME=" << testAppName << ';' + << "LOGIN_TIMEOUT_SEC=" << testLoginTimeoutSec << ';' + << "READ_PREFERENCE=" << testReadPreference << ';' + << " REPLICA_SET=" << testReplicaSet << ';' + << "RETRY_READS=" << BoolToStr(testRetryReads) << ';' + << "TLS =" << BoolToStr(testTlsFlag) << ';' + << " TLS_ALLOW_INVALID_HOSTNAMES=" << BoolToStr(testTlsAllowInvalidHostnamesFlag) << ';' + << "TLS_CA_FILE=" << testTlsCaFile << ';' + << " SSH_USER=" << testSshUser << ';' + << "SSH_HOST=" << testSshHost << ';' + << "SSH_PRIVATE_KEY_FILE= " << testSshPrivateKeyFile << ';' + << " SSH_PRIVATE_KEY_PASSPHRASE= " << testSshPrivateKeyPassphrase << ';' + << " SSH_STRICT_HOST_KEY_CHECKING= " << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' + << " SSH_KNOWN_HOSTS_FILE = " << testSshKnownHostsFile << ';' + << " SCAN_METHOD = " << testScanMethod << ';' + << " SCAN_LIMIT= " << testScanLimit << ';' + << "SCHEMA_NAME=" << testSchemaName << " ; " + << " REFRESH_SCHEMA=" << BoolToStr(testRefreshSchemaFlag) << ';' + << " DEFAULT_FETCH_SIZE = " << testDefaultFetchSize << " ; " + << "DRIVER = {" << testDriverName << "};"; const std::string& connectStr = constructor.str(); @@ -379,50 +494,26 @@ BOOST_AUTO_TEST_CASE(TestConnectStringInvalidAddress) { Configuration cfg; - ParseConnectStringWithError("Address=example.com:0;", cfg); - ParseConnectStringWithError("Address=example.com:00000;", cfg); - ParseConnectStringWithError("Address=example.com:fdsf;", cfg); - ParseConnectStringWithError("Address=example.com:123:1;", cfg); - ParseConnectStringWithError("Address=example.com:12322221;", cfg); - ParseConnectStringWithError("Address=example.com:12322a;", cfg); - ParseConnectStringWithError("Address=example.com:;", cfg); + ParseConnectStringWithError("hostname=example.com:0;", cfg); + ParseConnectStringWithError("hostname=example.com:00000;", cfg); + ParseConnectStringWithError("hostname=example.com:fdsf;", cfg); + ParseConnectStringWithError("hostname=example.com:123:1;", cfg); + ParseConnectStringWithError("hostname=example.com:12322221;", cfg); + ParseConnectStringWithError("hostname=example.com:12322a;", cfg); + ParseConnectStringWithError("hostname=example.com:;", cfg); } BOOST_AUTO_TEST_CASE(TestConnectStringValidAddress) { - CheckValidAddress("Address=example.com:1;", EndPoint("example.com", 1)); - CheckValidAddress("Address=example.com:31242;", EndPoint("example.com", 31242)); - CheckValidAddress("Address=example.com:55555;", EndPoint("example.com", 55555)); - CheckValidAddress("Address=example.com:110;", EndPoint("example.com", 110)); - CheckValidAddress("Address=example.com;", EndPoint("example.com", Configuration::DefaultValue::port)); - CheckValidAddress("Address=example.com:1000..1010;", EndPoint("example.com", 1000, 10)); -} - -BOOST_AUTO_TEST_CASE(TestConnectStringValidAddress4) -{ - std::vector addrs; - - addrs.push_back(EndPoint("one.com", 1234)); - addrs.push_back(EndPoint("two.net", 42, 53-42)); - addrs.push_back(EndPoint("three.eu", Configuration::DefaultValue::port)); - addrs.push_back(EndPoint("some.long.name.org", 50141)); - - CheckValidAddresses("Address=some.long.name.org:50141,three.eu,two.net:42..53,one.com:1234", addrs); -} - -BOOST_AUTO_TEST_CASE(TestConnectStringValidAddress4Spaces) -{ - std::vector addrs; - - addrs.push_back(EndPoint("one.com", 1234)); - addrs.push_back(EndPoint("two.net", 42, 53 - 42)); - addrs.push_back(EndPoint("three.eu", Configuration::DefaultValue::port)); - addrs.push_back(EndPoint("some.long.name.org", 50141)); - - CheckValidAddresses("Address = some.long.name.org:50141, three.eu, two.net: 42 .. 53, one.com:1234", addrs); + CheckValidAddress("hostname=example.com:1;", EndPoint("example.com", 1)); + CheckValidAddress("hostname=example.com:31242;", EndPoint("example.com", 31242)); + CheckValidAddress("hostname=example.com:55555;", EndPoint("example.com", 55555)); + CheckValidAddress("hostname=example.com:110;port=27019;", EndPoint("example.com", 27019)); + CheckValidAddress("hostname=example.com;", EndPoint("example.com", Configuration::DefaultValue::port)); + CheckValidAddress("hostname=example.com:1000..1010;", EndPoint("example.com", 1000, 10)); } -BOOST_AUTO_TEST_CASE(TestConnectStringInvalidVersion) +/*BOOST_AUTO_TEST_CASE(TestConnectStringInvalidVersion) { CheckInvalidProtocolVersion("Protocol_Version=0;"); CheckInvalidProtocolVersion("Protocol_Version=1;"); @@ -443,7 +534,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringSupportedVersion) CheckSupportedProtocolVersion("Protocol_Version=2.1.5;"); CheckSupportedProtocolVersion("Protocol_Version=2.3.0;"); CheckSupportedProtocolVersion("Protocol_Version=2.3.2;"); -} +}*/ BOOST_AUTO_TEST_CASE(TestConnectStringInvalidBoolKeys) { @@ -451,12 +542,11 @@ BOOST_AUTO_TEST_CASE(TestConnectStringInvalidBoolKeys) Set keys; - keys.insert("distributed_joins"); - keys.insert("enforce_join_order"); - keys.insert("replicated_only"); - keys.insert("collocated"); - keys.insert("lazy"); - keys.insert("skip_reducer_on_update"); + keys.insert("retry_reads"); + keys.insert("tls"); + keys.insert("tls_allow_invalid_hostnames"); + keys.insert("ssh_strict_host_key_checking"); + keys.insert("refresh_schema"); for (Set::const_iterator it = keys.begin(); it != keys.end(); ++it) { @@ -479,12 +569,11 @@ BOOST_AUTO_TEST_CASE(TestConnectStringValidBoolKeys) Set keys; - keys.insert("distributed_joins"); - keys.insert("enforce_join_order"); - keys.insert("replicated_only"); - keys.insert("collocated"); - keys.insert("lazy"); - keys.insert("skip_reducer_on_update"); + keys.insert("retry_reads"); + keys.insert("tls"); + keys.insert("tls_allow_invalid_hostnames"); + keys.insert("ssh_strict_host_key_checking"); + keys.insert("refresh_schema"); for (Set::const_iterator it = keys.begin(); it != keys.end(); ++it) { diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index c5a021c2d..a377e2dd0 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -52,13 +52,10 @@ namespace ignite /** Default value for Driver attribute. */ static const std::string driver; - /** Default value for schema attribute. */ + /** Default value for database attribute. */ static const std::string database; - /** Default value for address attribute. */ - static const std::string address; - - /** Default value for server attribute. */ + /** Default value for hostname attribute. */ static const std::string hostname; /** Default value for port attribute. */ @@ -85,9 +82,6 @@ namespace ignite /** Default value for retryReads attribute. */ static const bool retryReads; - /** Default value for sslMode attribute. */ - static const ssl::SslMode::Type sslMode; - /** Default value for tls attribute. */ static const bool tls; @@ -133,14 +127,8 @@ namespace ignite /** Default value for sslCertFile attribute. */ static const std::string sslCertFile; - /** Default value for protocol version. */ - // static const ProtocolVersion& protocolVersion; - - /** Default value for fetch results page size attribute. */ + /** Default value for defaultFetchSize attribute. */ static const int32_t defaultFetchSize; - - /** Default value for nestedTxMode attribute. */ - static const NestedTxMode::Type nestedTxMode; }; /** @@ -677,27 +665,6 @@ namespace ignite */ bool IsSchemaRefreshSet() const; - /** - * Get addresses. - * - * @return Addresses. - */ - const std::vector& GetAddresses() const; - - /** - * Set addresses to connect to. - * - * @param endPoints Addresses. - */ - void SetAddresses(const std::vector& endPoints); - - /** - * Check if the value set. - * - * @return @true if the value set. - */ - bool IsAddressesSet() const; - /** * Get fetch results page size. * @@ -773,9 +740,6 @@ namespace ignite /** Retry reads flag. */ SettableValue retryReads; - /** Connection end-points. */ - SettableValue< std::vector > endPoints; // Remove in favor of deprecated one - /** Enable SSL/TLS. */ SettableValue tls; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index c8832697c..b82716dac 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -135,7 +135,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - std::string addr = config::AddressesToString(config.GetAddresses()); + std::string addr = config.GetHostname(); val = addr.c_str(); addressLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, @@ -549,7 +549,7 @@ namespace ignite throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "Protocol version is not supported."); cfg.SetDsn(dsnStr); - cfg.SetAddresses(addresses); + //cfg.SetAddresses(addresses); cfg.SetDatabase(schemaStr); //cfg.SetProtocolVersion(version); } diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 198ecb9d0..bf4b9cadb 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -31,10 +31,9 @@ namespace ignite namespace config { - const std::string Configuration::DefaultValue::dsn = "Apache Ignite DSN"; - const std::string Configuration::DefaultValue::driver = "Apache Ignite"; + const std::string Configuration::DefaultValue::dsn = "DocumentDB DSN"; + const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB Driver"; // remove const std::string Configuration::DefaultValue::database = ""; - const std::string Configuration::DefaultValue::address = ""; // remove const std::string Configuration::DefaultValue::hostname = ""; const uint16_t Configuration::DefaultValue::port = 27017; const std::string Configuration::DefaultValue::user = ""; @@ -62,13 +61,11 @@ namespace ignite // Additional options const std::string Configuration::DefaultValue::appName = "Amazon DocumentDB ODBC Driver"; const int32_t Configuration::DefaultValue::loginTimeoutSec = 0; - const std::string Configuration::DefaultValue::readPreference = ""; + const std::string Configuration::DefaultValue::readPreference = "primary"; const std::string Configuration::DefaultValue::replicaSet = ""; const bool Configuration::DefaultValue::retryReads = true; const int32_t Configuration::DefaultValue::defaultFetchSize = 2000; - const NestedTxMode::Type Configuration::DefaultValue::nestedTxMode = NestedTxMode::AI_ERROR; // remove - Configuration::Configuration() : dsn(DefaultValue::dsn), driver(DefaultValue::driver), @@ -77,7 +74,6 @@ namespace ignite port(DefaultValue::port), user(DefaultValue::user), password(DefaultValue::password), - endPoints(std::vector()), appName(DefaultValue::appName), loginTimeoutSec(DefaultValue::loginTimeoutSec), readPreference(DefaultValue::readPreference), @@ -204,21 +200,6 @@ namespace ignite return database.IsSet(); } - const std::vector& Configuration::GetAddresses() const - { - return endPoints.GetValue(); - } - - void Configuration::SetAddresses(const std::vector& endPoints) - { - this->endPoints.SetValue(endPoints); - } - - bool Configuration::IsAddressesSet() const - { - return endPoints.IsSet(); - } - const std::string& Configuration::GetApplicationName() const { return appName.GetValue(); @@ -540,7 +521,6 @@ namespace ignite AddToMap(res, ConnectionStringParser::Key::dsn, dsn); AddToMap(res, ConnectionStringParser::Key::driver, driver); AddToMap(res, ConnectionStringParser::Key::database, database); - AddToMap(res, ConnectionStringParser::Key::address, endPoints); AddToMap(res, ConnectionStringParser::Key::server, hostname); AddToMap(res, ConnectionStringParser::Key::port, port); AddToMap(res, ConnectionStringParser::Key::user, user); diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index 308bb225b..489fa624c 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -35,7 +35,7 @@ namespace ignite const std::string ConnectionStringParser::Key::driver = "driver"; const std::string ConnectionStringParser::Key::database = "database"; const std::string ConnectionStringParser::Key::address = "address"; - const std::string ConnectionStringParser::Key::server = "server"; + const std::string ConnectionStringParser::Key::server = "hostname"; const std::string ConnectionStringParser::Key::port = "port"; const std::string ConnectionStringParser::Key::user = "user"; const std::string ConnectionStringParser::Key::password = "password"; @@ -151,17 +151,16 @@ namespace ignite { cfg.SetDatabase(value); } - else if (lKey == Key::address) + else if (lKey == Key::server) { - std::vector endPoints; + EndPoint endpoint; - ParseAddress(value, endPoints, diag); + ParseSingleAddress(value, endpoint, diag); - cfg.SetAddresses(endPoints); - } - else if (lKey == Key::server) - { - cfg.SetHostname(value); + cfg.SetHostname(endpoint.host); + + if (!cfg.IsTcpPortSet()) + cfg.SetTcpPort(endpoint.port); } else if (lKey == Key::port) { @@ -255,7 +254,7 @@ namespace ignite return; } - cfg.SetScanLimit(static_cast(numValue)); + cfg.SetLoginTimeoutSeconds(static_cast(numValue)); } else if (lKey == Key::readPreference) { @@ -265,6 +264,23 @@ namespace ignite { cfg.SetReplicaSet(value); } + else if (lKey == Key::retryReads) + { + BoolParseResult::Type res = StringToBool(value); + + if (res == BoolParseResult::AI_UNRECOGNIZED) + { + if (diag) + { + diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, + MakeErrorMessage("Unrecognized bool value. Using default value.", key, value)); + } + + return; + } + + cfg.SetRetryReads(res == BoolParseResult::AI_TRUE); + } else if (lKey == Key::tls) { BoolParseResult::Type res = StringToBool(value); @@ -397,7 +413,7 @@ namespace ignite return; } - cfg.SetTls(res == BoolParseResult::AI_TRUE); + cfg.SetSchemaRefresh(res == BoolParseResult::AI_TRUE); } else if (lKey == Key::defaultFetchSize) { diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index c2875fd7e..b347c5035 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -188,7 +188,7 @@ namespace ignite return SqlResult::AI_ERROR; } - if (!config.IsHostnameSet() && config.IsAddressesSet() && config.GetAddresses().empty()) + if (!config.IsHostnameSet()) { AddStatusRecord("No valid address to connect."); @@ -780,7 +780,12 @@ namespace ignite { endPoints.clear(); - if (!cfg.IsAddressesSet()) + // DocumentDB driver is currently not supporting list of addresses. Always use this 'legacy' method. + LOG_MSG("'Address' is not set. Using legacy connection method."); + endPoints.push_back(EndPoint(cfg.GetHostname(), cfg.GetTcpPort())); + return; + + /*if (!cfg.IsAddressesSet()) { LOG_MSG("'Address' is not set. Using legacy connection method."); @@ -790,8 +795,10 @@ namespace ignite } endPoints = cfg.GetAddresses(); + std::random_shuffle(endPoints.begin(), endPoints.end()); + */ } int32_t Connection::RetrieveTimeout(void* value) diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 6526a38bd..564d6b272 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -104,17 +104,6 @@ namespace ignite void ReadDsnConfiguration(const char* dsn, Configuration& config, diagnostic::DiagnosticRecordStorage* diag) { - SettableValue address = ReadDsnString(dsn, ConnectionStringParser::Key::address); - - if (address.IsSet() && !config.IsAddressesSet()) - { - std::vector endPoints; - - ParseAddress(address.GetValue(), endPoints, diag); - - config.SetAddresses(endPoints); - } - SettableValue server = ReadDsnString(dsn, ConnectionStringParser::Key::server); if (server.IsSet() && !config.IsHostnameSet()) From 8a5a35749804915319b37c63a0004c749991b409 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 09:20:47 -0800 Subject: [PATCH 023/165] [AD-522] add space to code lines for format consistency in configuration_window.h --- .../odbc/system/ui/dsn_configuration_window.h | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index ad8c45e99..5779ee7bf 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -242,37 +242,37 @@ namespace ignite std::auto_ptr schemaEdit; /** Application name edit. */ - std::auto_ptr appNameEdit; + std::auto_ptr appNameEdit; /** Application name label. */ - std::auto_ptr appNameLabel; + std::auto_ptr appNameLabel; /** Login Timeout (seconds) edit. */ - std::auto_ptr loginTimeoutSecEdit; + std::auto_ptr loginTimeoutSecEdit; /** Login Timeout (seconds) label. */ - std::auto_ptr loginTimeoutSecLabel; + std::auto_ptr loginTimeoutSecLabel; /** Read preference edit. */ - std::auto_ptr readPreferenceEdit; + std::auto_ptr readPreferenceEdit; /** Read preference label. */ - std::auto_ptr readPreferenceLabel; + std::auto_ptr readPreferenceLabel; /** Replica Set edit. */ - std::auto_ptr< Window > replicaSetEdit; + std::auto_ptr< Window > replicaSetEdit; /** Replica Set label. */ - std::auto_ptr< Window > replicaSetLabel; + std::auto_ptr< Window > replicaSetLabel; /** Retry reads CheckBox. */ - std::auto_ptr retryReadsCheckBox; + std::auto_ptr retryReadsCheckBox; /** Fetch size edit. */ - std::auto_ptr fetchSizeEdit; + std::auto_ptr fetchSizeEdit; /** Fetch size label. */ - std::auto_ptr fetchSizeLabel; + std::auto_ptr fetchSizeLabel; /** Protocol version edit field. */ std::auto_ptr protocolVersionLabel; From 504d2bacc47bbfb4f33e968a6ae8af10633f523b Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Thu, 20 Jan 2022 09:25:19 -0800 Subject: [PATCH 024/165] Add more unit tests --- src/odbc-test/CMakeLists.txt | 54 +++-- src/odbc-test/src/configuration_test.cpp | 106 +++++---- src/odbc/CMakeLists.txt | 4 +- .../ignite/odbc/config/configuration.h | 217 +++++++++--------- .../include/ignite/odbc/read_preference.h | 61 +++++ src/odbc/include/ignite/odbc/scan_method.h | 59 +++++ src/odbc/src/config/configuration.cpp | 64 ++---- .../src/config/connection_string_parser.cpp | 32 ++- src/odbc/src/dsn_config.cpp | 14 +- src/odbc/src/read_preference.cpp | 74 ++++++ src/odbc/src/scan_method.cpp | 68 ++++++ 11 files changed, 528 insertions(+), 225 deletions(-) create mode 100644 src/odbc/include/ignite/odbc/read_preference.h create mode 100644 src/odbc/include/ignite/odbc/scan_method.h create mode 100644 src/odbc/src/read_preference.cpp create mode 100644 src/odbc/src/scan_method.cpp diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index ae4ab2274..96276e8e3 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -33,6 +33,18 @@ include_directories(include ../odbc/include ../network/include) set(SOURCES src/dummy_test.cpp src/configuration_test.cpp + ../odbc/src/config/config_tools.cpp + ../odbc/src/config/configuration.cpp + ../odbc/src/config/connection_info.cpp + ../odbc/src/config/connection_string_parser.cpp + ../odbc/src/scan_method.cpp + ../odbc/src/read_preference.cpp + ../odbc/src/diagnostic/diagnostic_record.cpp + ../odbc/src/diagnostic/diagnostic_record_storage.cpp + ../odbc/src/utility.cpp + ../odbc/src/common_types.cpp + ../odbc/src/app/application_data_buffer.cpp + ../odbc/src/log.cpp # TODO uncomment/rework the tests after get some connectivity and functionalities working. # src/teamcity/teamcity_boost.cpp # src/teamcity/teamcity_messages.cpp @@ -72,27 +84,27 @@ set(SOURCES # src/streaming_test.cpp # src/cursor_binding_test.cpp # src/test_server.cpp - ../odbc/src/log.cpp - ../odbc/src/cursor.cpp - ../odbc/src/diagnostic/diagnostic_record.cpp - ../odbc/src/diagnostic/diagnostic_record_storage.cpp - ../odbc/src/config/config_tools.cpp - ../odbc/src/config/configuration.cpp - ../odbc/src/config/connection_info.cpp - ../odbc/src/config/connection_string_parser.cpp - ../odbc/src/app/application_data_buffer.cpp - ../odbc/src/ssl_mode.cpp - ../odbc/src/sql/sql_parser.cpp - ../odbc/src/sql/sql_lexer.cpp - ../odbc/src/sql/sql_set_streaming_command.cpp - ../odbc/src/sql/sql_utils.cpp - ../odbc/src/row.cpp - ../odbc/src/protocol_version.cpp - ../odbc/src/column.cpp - ../odbc/src/common_types.cpp - ../odbc/src/utility.cpp - ../odbc/src/result_page.cpp - ../odbc/src/nested_tx_mode.cpp +# ../odbc/src/log.cpp +# ../odbc/src/cursor.cpp +# ../odbc/src/diagnostic/diagnostic_record.cpp +# ../odbc/src/diagnostic/diagnostic_record_storage.cpp +# ../odbc/src/config/config_tools.cpp +# ../odbc/src/config/configuration.cpp +# ../odbc/src/config/connection_info.cpp +# ../odbc/src/config/connection_string_parser.cpp +# ../odbc/src/app/application_data_buffer.cpp +# ../odbc/src/ssl_mode.cpp +# ../odbc/src/sql/sql_parser.cpp +# ../odbc/src/sql/sql_lexer.cpp +# ../odbc/src/sql/sql_set_streaming_command.cpp +# ../odbc/src/sql/sql_utils.cpp +# ../odbc/src/row.cpp +# ../odbc/src/protocol_version.cpp +# ../odbc/src/column.cpp +# ../odbc/src/common_types.cpp +# ../odbc/src/utility.cpp +# ../odbc/src/result_page.cpp +# ../odbc/src/nested_tx_mode.cpp ) add_executable(${TARGET} ${SOURCES}) diff --git a/src/odbc-test/src/configuration_test.cpp b/src/odbc-test/src/configuration_test.cpp index 9d21d1f60..d2c441280 100644 --- a/src/odbc-test/src/configuration_test.cpp +++ b/src/odbc-test/src/configuration_test.cpp @@ -41,7 +41,7 @@ namespace const std::string testPassword = "testPassword"; const std::string testAppName = "testAppName"; const int32_t testLoginTimeoutSec = 3000; - const std::string testReadPreference = "primaryPreferred"; + const ReadPreference::Type testReadPreference = ReadPreference::Type::PRIMARY_PREFERRED; const std::string testReplicaSet = "rs0"; const bool testRetryReads = false; const bool testTlsFlag = false; @@ -53,7 +53,7 @@ namespace const std::string testSshPrivateKeyPassphrase = "testPassphrase"; const bool testSshStrictHostKeyCheckingFlag = false; const std::string testSshKnownHostsFile = "/path/to/knownhostsfile"; - const std::string testScanMethod = "idForward"; + const ScanMethod::Type testScanMethod =ScanMethod::Type::ID_FORWARD; const int32_t testScanLimit = 3000; const std::string testSchemaName = "testSchemaName"; const bool testRefreshSchemaFlag = true; @@ -115,31 +115,42 @@ void CheckValidAddress(const char* connectStr, const EndPoint& endPoint) BOOST_CHECK_EQUAL(cfg.GetTcpPort(), endPoint.port); } -void CheckValidProtocolVersion(const char* connectStr, ProtocolVersion version) +void CheckValidScanMethod(const char* connectStr, ScanMethod::Type scanMethod) { Configuration cfg; ParseValidConnectString(connectStr, cfg); - //BOOST_CHECK(cfg.GetProtocolVersion() == version); + BOOST_CHECK(cfg.GetScanMethod() == scanMethod); } -void CheckSupportedProtocolVersion(const char* connectStr) + +void CheckInvalidScanMethod(const char* connectStr) +{ + Configuration cfg; + + ParseConnectStringWithError(connectStr, cfg); + + BOOST_CHECK(cfg.GetScanMethod() == Configuration::DefaultValue::scanMethod); +} + +void CheckValidReadPreference(const char* connectStr, ReadPreference::Type preference) { Configuration cfg; ParseValidConnectString(connectStr, cfg); - //BOOST_CHECK(cfg.GetProtocolVersion().IsSupported()); + BOOST_CHECK(cfg.GetReadPreference() == preference); } -void CheckInvalidProtocolVersion(const char* connectStr) + +void CheckInvalidReadPreference(const char* connectStr) { Configuration cfg; ParseConnectStringWithError(connectStr, cfg); - //BOOST_CHECK(cfg.GetProtocolVersion() == Configuration::DefaultValue::protocolVersion); + BOOST_CHECK(cfg.GetReadPreference() == Configuration::DefaultValue::readPreference); } void CheckValidBoolValue(const std::string& connectStr, const std::string& key, bool val) @@ -178,7 +189,6 @@ void CheckConnectionConfig(const Configuration& cfg) BOOST_CHECK_EQUAL(cfg.GetPassword(), testPassword); BOOST_CHECK_EQUAL(cfg.GetApplicationName(), testAppName); BOOST_CHECK_EQUAL(cfg.GetLoginTimeoutSeconds(), testLoginTimeoutSec); - BOOST_CHECK_EQUAL(cfg.GetReadPreference(), testReadPreference); BOOST_CHECK_EQUAL(cfg.GetReplicaSet(), testReplicaSet); BOOST_CHECK_EQUAL(cfg.IsRetryReads(), testRetryReads); BOOST_CHECK_EQUAL(cfg.IsTls(), testTlsFlag); @@ -190,13 +200,13 @@ void CheckConnectionConfig(const Configuration& cfg) BOOST_CHECK_EQUAL(cfg.GetSshPrivateKeyPassphrase(), testSshPrivateKeyPassphrase); BOOST_CHECK_EQUAL(cfg.IsSshStrictHostKeyChecking(), testSshStrictHostKeyCheckingFlag); BOOST_CHECK_EQUAL(cfg.GetSshKnownHostsFile(), testSshKnownHostsFile); - BOOST_CHECK_EQUAL(cfg.GetScanMethod(), testScanMethod); BOOST_CHECK_EQUAL(cfg.GetScanLimit(), testScanLimit); BOOST_CHECK_EQUAL(cfg.GetSchemaName(), testSchemaName); - BOOST_CHECK_EQUAL(cfg.IsSchemaRefresh(), testRefreshSchemaFlag); + BOOST_CHECK_EQUAL(cfg.IsRefreshSchema(), testRefreshSchemaFlag); BOOST_CHECK_EQUAL(cfg.GetDefaultFetchSize(), testDefaultFetchSize); - BOOST_CHECK(!cfg.IsDsnSet()); + BOOST_CHECK(cfg.GetReadPreference() == testReadPreference); + BOOST_CHECK(cfg.GetScanMethod() == testScanMethod); std::stringstream constructor; @@ -208,12 +218,12 @@ void CheckConnectionConfig(const Configuration& cfg) << "login_timeout_sec=" << testLoginTimeoutSec << ';' << "password=" << testPassword << ';' << "port=" << testServerPort << ';' - << "read_preference=" << testReadPreference << ';' + << "read_preference=" << ReadPreference::ToString(testReadPreference) << ';' << "refresh_schema=" << BoolToStr(testRefreshSchemaFlag) << ';' << "replica_set=" << testReplicaSet << ';' << "retry_reads=" << BoolToStr(testRetryReads) << ';' << "scan_limit=" << testScanLimit << ';' - << "scan_method=" << testScanMethod << ';' + << "scan_method=" << ScanMethod::ToString(testScanMethod) << ';' << "schema_name=" << testSchemaName << ';' << "ssh_host=" << testSshHost << ';' << "ssh_known_hosts_file=" << testSshKnownHostsFile << ';' @@ -242,7 +252,6 @@ void CheckDsnConfig(const Configuration& cfg) BOOST_CHECK_EQUAL(cfg.GetPassword(), Configuration::DefaultValue::password); BOOST_CHECK_EQUAL(cfg.GetApplicationName(), Configuration::DefaultValue::appName); BOOST_CHECK_EQUAL(cfg.GetLoginTimeoutSeconds(), Configuration::DefaultValue::loginTimeoutSec); - BOOST_CHECK_EQUAL(cfg.GetReadPreference(), Configuration::DefaultValue::readPreference); BOOST_CHECK_EQUAL(cfg.GetReplicaSet(), Configuration::DefaultValue::replicaSet); BOOST_CHECK_EQUAL(cfg.IsRetryReads(), Configuration::DefaultValue::retryReads); BOOST_CHECK_EQUAL(cfg.IsTls(), Configuration::DefaultValue::tls); @@ -254,11 +263,12 @@ void CheckDsnConfig(const Configuration& cfg) BOOST_CHECK_EQUAL(cfg.GetSshPrivateKeyPassphrase(), Configuration::DefaultValue::sshPrivateKeyPassphrase); BOOST_CHECK_EQUAL(cfg.IsSshStrictHostKeyChecking(), Configuration::DefaultValue::sshStrictHostKeyChecking); BOOST_CHECK_EQUAL(cfg.GetSshKnownHostsFile(), Configuration::DefaultValue::sshKnownHostsFile); - BOOST_CHECK_EQUAL(cfg.GetScanMethod(), Configuration::DefaultValue::scanMethod); BOOST_CHECK_EQUAL(cfg.GetScanLimit(), Configuration::DefaultValue::scanLimit); BOOST_CHECK_EQUAL(cfg.GetSchemaName(), Configuration::DefaultValue::schemaName); - BOOST_CHECK_EQUAL(cfg.IsSchemaRefresh(), Configuration::DefaultValue::refreshSchema); + BOOST_CHECK_EQUAL(cfg.IsRefreshSchema(), Configuration::DefaultValue::refreshSchema); BOOST_CHECK_EQUAL(cfg.GetDefaultFetchSize(), Configuration::DefaultValue::defaultFetchSize); + BOOST_CHECK(cfg.GetReadPreference() == Configuration::DefaultValue::readPreference); + BOOST_CHECK(cfg.GetScanMethod() == Configuration::DefaultValue::scanMethod); } BOOST_AUTO_TEST_SUITE(ConfigurationTestSuite) @@ -274,7 +284,6 @@ BOOST_AUTO_TEST_CASE(CheckTestValuesNotEqualDefault) BOOST_CHECK_NE(testPassword, Configuration::DefaultValue::password); BOOST_CHECK_NE(testAppName, Configuration::DefaultValue::appName); BOOST_CHECK_NE(testLoginTimeoutSec, Configuration::DefaultValue::loginTimeoutSec); - BOOST_CHECK_NE(testReadPreference, Configuration::DefaultValue::readPreference); BOOST_CHECK_NE(testReplicaSet, Configuration::DefaultValue::replicaSet); BOOST_CHECK_NE(testRetryReads, Configuration::DefaultValue::retryReads); BOOST_CHECK_NE(testTlsFlag, Configuration::DefaultValue::tls); @@ -286,11 +295,12 @@ BOOST_AUTO_TEST_CASE(CheckTestValuesNotEqualDefault) BOOST_CHECK_NE(testSshPrivateKeyPassphrase, Configuration::DefaultValue::sshPrivateKeyPassphrase); BOOST_CHECK_NE(testSshStrictHostKeyCheckingFlag, Configuration::DefaultValue::sshStrictHostKeyChecking); BOOST_CHECK_NE(testSshKnownHostsFile, Configuration::DefaultValue::sshKnownHostsFile); - BOOST_CHECK_NE(testScanMethod, Configuration::DefaultValue::scanMethod); BOOST_CHECK_NE(testScanLimit, Configuration::DefaultValue::scanLimit); BOOST_CHECK_NE(testSchemaName, Configuration::DefaultValue::schemaName); BOOST_CHECK_NE(testRefreshSchemaFlag, Configuration::DefaultValue::refreshSchema); BOOST_CHECK_NE(testDefaultFetchSize, Configuration::DefaultValue::defaultFetchSize); + BOOST_CHECK(testReadPreference != Configuration::DefaultValue::readPreference); + BOOST_CHECK(testScanMethod != Configuration::DefaultValue::scanMethod); } BOOST_AUTO_TEST_CASE(TestConnectStringUppercase) @@ -306,7 +316,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringUppercase) << "PASSWORD=" << testPassword << ';' << "APP_NAME=" << testAppName << ';' << "LOGIN_TIMEOUT_SEC=" << testLoginTimeoutSec << ';' - << "READ_PREFERENCE=" << testReadPreference << ';' + << "READ_PREFERENCE=" << ReadPreference::ToString(testReadPreference) << ';' << "REPLICA_SET=" << testReplicaSet << ';' << "RETRY_READS=" << BoolToStr(testRetryReads) << ';' << "TLS=" << BoolToStr(testTlsFlag) << ';' @@ -318,7 +328,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringUppercase) << "SSH_PRIVATE_KEY_PASSPHRASE=" << testSshPrivateKeyPassphrase << ';' << "SSH_STRICT_HOST_KEY_CHECKING=" << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' << "SSH_KNOWN_HOSTS_FILE=" << testSshKnownHostsFile << ';' - << "SCAN_METHOD=" << testScanMethod << ';' + << "SCAN_METHOD=" << ScanMethod::ToString(testScanMethod) << ';' << "SCAN_LIMIT=" << testScanLimit << ';' << "SCHEMA_NAME=" << testSchemaName << ';' << "REFRESH_SCHEMA=" << BoolToStr(testRefreshSchemaFlag) << ';' @@ -345,7 +355,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringLowercase) << "password=" << testPassword << ';' << "app_name=" << testAppName << ';' << "login_timeout_sec=" << testLoginTimeoutSec << ';' - << "read_preference=" << testReadPreference << ';' + << "read_preference=" << ReadPreference::ToString(testReadPreference) << ';' << "replica_set=" << testReplicaSet << ';' << "retry_reads=" << BoolToStr(testRetryReads) << ';' << "tls=" << BoolToStr(testTlsFlag) << ';' @@ -357,7 +367,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringLowercase) << "ssh_private_key_passphrase=" << testSshPrivateKeyPassphrase << ';' << "ssh_strict_host_key_checking=" << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' << "ssh_known_hosts_file=" << testSshKnownHostsFile << ';' - << "scan_method=" << testScanMethod << ';' + << "scan_method=" << ScanMethod::ToString(testScanMethod) << ';' << "scan_limit=" << testScanLimit << ';' << "schema_name=" << testSchemaName << ';' << "refresh_schema=" << BoolToStr(testRefreshSchemaFlag) << ';' @@ -384,7 +394,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringZeroTerminated) << "password=" << testPassword << ';' << "app_name=" << testAppName << ';' << "login_timeout_sec=" << testLoginTimeoutSec << ';' - << "read_preference=" << testReadPreference << ';' + << "read_preference=" << ReadPreference::ToString(testReadPreference) << ';' << "replica_set=" << testReplicaSet << ';' << "retry_reads=" << BoolToStr(testRetryReads) << ';' << "tls=" << BoolToStr(testTlsFlag) << ';' @@ -396,7 +406,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringZeroTerminated) << "ssh_private_key_passphrase=" << testSshPrivateKeyPassphrase << ';' << "ssh_strict_host_key_checking=" << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' << "ssh_known_hosts_file=" << testSshKnownHostsFile << ';' - << "scan_method=" << testScanMethod << ';' + << "scan_method=" << ScanMethod::ToString(testScanMethod) << ';' << "scan_limit=" << testScanLimit << ';' << "schema_name=" << testSchemaName << ';' << "refresh_schema=" << BoolToStr(testRefreshSchemaFlag) << ';' @@ -425,7 +435,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringMixed) << "Password=" << testPassword << ';' << "App_Name=" << testAppName << ';' << "Login_Timeout_Sec=" << testLoginTimeoutSec << ';' - << "Read_Preference=" << testReadPreference << ';' + << "Read_Preference=" << ReadPreference::ToString(testReadPreference) << ';' << "Replica_Set=" << testReplicaSet << ';' << "Retry_Reads=" << BoolToStr(testRetryReads) << ';' << "Tls=" << BoolToStr(testTlsFlag) << ';' @@ -437,7 +447,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringMixed) << "Ssh_Private_Key_Passphrase=" << testSshPrivateKeyPassphrase << ';' << "Ssh_Strict_Host_Key_Checking=" << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' << "Ssh_Known_Hosts_File=" << testSshKnownHostsFile << ';' - << "Scan_Method=" << testScanMethod << ';' + << "Scan_Method=" << ScanMethod::ToString(testScanMethod) << ';' << "Scan_Limit=" << testScanLimit << ';' << "Schema_Name=" << testSchemaName << ';' << "Refresh_Schema=" << BoolToStr(testRefreshSchemaFlag) << ';' @@ -464,7 +474,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringWhitepaces) << "PASSWORD=" << testPassword << ';' << "APP_NAME=" << testAppName << ';' << "LOGIN_TIMEOUT_SEC=" << testLoginTimeoutSec << ';' - << "READ_PREFERENCE=" << testReadPreference << ';' + << "READ_PREFERENCE=" << ReadPreference::ToString(testReadPreference) << ';' << " REPLICA_SET=" << testReplicaSet << ';' << "RETRY_READS=" << BoolToStr(testRetryReads) << ';' << "TLS =" << BoolToStr(testTlsFlag) << ';' @@ -476,7 +486,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringWhitepaces) << " SSH_PRIVATE_KEY_PASSPHRASE= " << testSshPrivateKeyPassphrase << ';' << " SSH_STRICT_HOST_KEY_CHECKING= " << BoolToStr(testSshStrictHostKeyCheckingFlag) << ';' << " SSH_KNOWN_HOSTS_FILE = " << testSshKnownHostsFile << ';' - << " SCAN_METHOD = " << testScanMethod << ';' + << " SCAN_METHOD = " << ScanMethod::ToString(testScanMethod) << ';' << " SCAN_LIMIT= " << testScanLimit << ';' << "SCHEMA_NAME=" << testSchemaName << " ; " << " REFRESH_SCHEMA=" << BoolToStr(testRefreshSchemaFlag) << ';' @@ -513,28 +523,34 @@ BOOST_AUTO_TEST_CASE(TestConnectStringValidAddress) CheckValidAddress("hostname=example.com:1000..1010;", EndPoint("example.com", 1000, 10)); } -/*BOOST_AUTO_TEST_CASE(TestConnectStringInvalidVersion) +BOOST_AUTO_TEST_CASE(TestConnectStringInvalidScanMethod) { - CheckInvalidProtocolVersion("Protocol_Version=0;"); - CheckInvalidProtocolVersion("Protocol_Version=1;"); - CheckInvalidProtocolVersion("Protocol_Version=2;"); - CheckInvalidProtocolVersion("Protocol_Version=2.1;"); + CheckInvalidScanMethod("scan_method=forward;"); + CheckInvalidScanMethod("scan_method=id_random;"); } -BOOST_AUTO_TEST_CASE(TestConnectStringUnsupportedVersion) +BOOST_AUTO_TEST_CASE(TestConnectStringValidScanMethod) { - CheckInvalidProtocolVersion("Protocol_Version=1.6.1;"); - CheckInvalidProtocolVersion("Protocol_Version=1.7.0;"); - CheckInvalidProtocolVersion("Protocol_Version=1.8.1;"); + CheckValidScanMethod("scan_method=all;", ScanMethod::Type::ALL); + CheckValidScanMethod("scan_method=id_forward;", ScanMethod::Type::ID_FORWARD); + CheckValidScanMethod("scan_method=id_reverse;", ScanMethod::Type::ID_REVERSE); + CheckValidScanMethod("scan_method=random;", ScanMethod::Type::RANDOM); } -BOOST_AUTO_TEST_CASE(TestConnectStringSupportedVersion) +BOOST_AUTO_TEST_CASE(TestConnectStringInvalidReadPreference) { - CheckSupportedProtocolVersion("Protocol_Version=2.1.0;"); - CheckSupportedProtocolVersion("Protocol_Version=2.1.5;"); - CheckSupportedProtocolVersion("Protocol_Version=2.3.0;"); - CheckSupportedProtocolVersion("Protocol_Version=2.3.2;"); -}*/ + CheckInvalidReadPreference("read_preference=primary_nearest;"); + CheckInvalidReadPreference("read_preference=nearest_preferred;"); +} + +BOOST_AUTO_TEST_CASE(TestConnectStringValidReadPreference) +{ + CheckValidReadPreference("read_preference=primary;", ReadPreference::Type::PRIMARY); + CheckValidReadPreference("read_preference=primary_preferred;", ReadPreference::Type::PRIMARY_PREFERRED); + CheckValidReadPreference("read_preference=secondary;", ReadPreference::Type::SECONDARY); + CheckValidReadPreference("read_preference=secondary_preferred;", ReadPreference::Type::SECONDARY_PREFERRED); + CheckValidReadPreference("read_preference=nearest;", ReadPreference::Type::NEAREST); +} BOOST_AUTO_TEST_CASE(TestConnectStringInvalidBoolKeys) { @@ -653,4 +669,4 @@ BOOST_AUTO_TEST_CASE(TestDsnStringWhitespaces) CheckDsnConfig(cfg); } -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() \ No newline at end of file diff --git a/src/odbc/CMakeLists.txt b/src/odbc/CMakeLists.txt index 4c251a97b..522dd1392 100644 --- a/src/odbc/CMakeLists.txt +++ b/src/odbc/CMakeLists.txt @@ -68,7 +68,9 @@ set(SOURCES src/app/application_data_buffer.cpp src/statement.cpp src/type_traits.cpp src/utility.cpp - src/log.cpp) + src/log.cpp + src/read_preference.cpp + src/scan_method.cpp) if (WIN32) include_directories(os/win/include) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index a377e2dd0..a7b87ad5c 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -27,6 +27,8 @@ #include "ignite/odbc/ssl_mode.h" #include "ignite/odbc/end_point.h" #include "ignite/odbc/nested_tx_mode.h" +#include "ignite/odbc/read_preference.h" +#include "ignite/odbc/scan_method.h" namespace ignite { @@ -74,7 +76,7 @@ namespace ignite static const int32_t loginTimeoutSec; /** Default value for readPreference attribute. */ - static const std::string readPreference; + static const ReadPreference::Type readPreference; /** Default value for replicaSet attribute. */ static const std::string replicaSet; @@ -110,7 +112,7 @@ namespace ignite static const std::string sshKnownHostsFile; /** Default value for scanMethod attribute. */ - static const std::string scanMethod; + static const ScanMethod::Type scanMethod; /** Default value for scanLimit attribute. */ static const int32_t scanLimit; @@ -167,7 +169,7 @@ namespace ignite * * @param dsn Data Source Name. */ - void SetDsn(const std::string& dsn); + void SetDsn(const std::string& dsnName); /** * Get Driver. @@ -181,7 +183,7 @@ namespace ignite * * @param driver Driver. */ - void SetDriver(const std::string& driver); + void SetDriver(const std::string& driverName); /** * Get server host. @@ -214,9 +216,9 @@ namespace ignite /** * Set server port. * - * @param port Server port. + * @param portNumber Server port. */ - void SetTcpPort(uint16_t port); + void SetTcpPort(uint16_t portNumber); /** * Check if the value set. @@ -226,18 +228,18 @@ namespace ignite bool IsTcpPortSet() const; /** - * Get schema. + * Get database. * - * @return Schema. + * @return Database. */ const std::string& GetDatabase() const; /** * Set schema. * - * @param schema Schema name. + * @param database Database name. */ - void SetDatabase(const std::string& schema); + void SetDatabase(const std::string& databaseName); /** * Check if the value set. @@ -258,7 +260,7 @@ namespace ignite * * @param user User. */ - void SetUser(const std::string& user); + void SetUser(const std::string& username); /** * Check if the value set. @@ -289,16 +291,16 @@ namespace ignite bool IsPasswordSet() const; /** - * Get password. + * Get application name. * - * @return Password. + * @return Application name. */ const std::string& GetApplicationName() const; /** - * Set password. + * Set application name. * - * @param pass Password. + * @param name Application name. */ void SetApplicationName(const std::string& name); @@ -310,16 +312,16 @@ namespace ignite bool IsApplicationNameSet() const; /** - * Get fetch results page size. + * Get login timeout in seconds. * - * @return Fetch results page size. + * @return Login timeout in seconds. */ int32_t GetLoginTimeoutSeconds() const; /** - * Set fetch results page size. + * Set login timeout in seconds. * - * @param size Fetch results page size. + * @param seconds Login timeout in seconds. */ void SetLoginTimeoutSeconds(int32_t seconds); @@ -331,18 +333,18 @@ namespace ignite bool IsLoginTimeoutSecondsSet() const; /** - * Get password. + * Get read preference. * - * @return Password. + * @return Read preference. */ - const std::string& GetReadPreference() const; + ReadPreference::Type GetReadPreference() const; /** - * Set password. + * Set read preference. * - * @param pass Password. + * @param preference Read preference. */ - void SetReadPreference(const std::string& preference); + void SetReadPreference(const ReadPreference::Type preference); /** * Check if the value set. @@ -350,17 +352,18 @@ namespace ignite * @return @true if the value set. */ bool IsReadPreferenceSet() const; + /** - * Get password. + * Get replica set name. * - * @return Password. + * @return Replica set name. */ const std::string& GetReplicaSet() const; /** - * Set password. + * Set replica set name. * - * @param pass Password. + * @param name Replica set name. */ void SetReplicaSet(const std::string& name); @@ -372,16 +375,16 @@ namespace ignite bool IsReplicaSetSet() const; /** - * Get password. + * Get retry reads flag. * - * @return Password. + * @return @true if retry reads enabled. */ bool IsRetryReads() const; /** - * Set password. + * Set retry reads. * - * @param pass Password. + * @param val Value to set. */ void SetRetryReads(bool val); @@ -393,16 +396,16 @@ namespace ignite bool IsRetryReadsSet() const; /** - * Get password. + * Get TLS flag. * - * @return Password. + * @return @true if TLS is enabled. */ bool IsTls() const; /** - * Set password. + * Set TLS flag. * - * @param pass Password. + * @param val Value to set. */ void SetTls(bool val); @@ -414,16 +417,16 @@ namespace ignite bool IsTlsSet() const; /** - * Get password. + * Get TLS allow invalid hostnames flag. * - * @return Password. + * @return @true if invalid hostnames are allowed with TLS. */ bool IsTlsAllowInvalidHostnames() const; /** - * Set password. + * Set TLS allow invaid hostnames flag. * - * @param pass Password. + * @param val Value to set. */ void SetTlsAllowInvalidHostnames(bool val); @@ -435,16 +438,16 @@ namespace ignite bool IsTlsAllowInvalidHostnamesSet() const; /** - * Get password. + * Get path to TLS CA file. * - * @return Password. + * @return path to TLS CA file. */ const std::string& GetTlsCaFile() const; /** - * Set password. + * Set path to TLS CA file. * - * @param pass Password. + * @param path Path to TLS CA file. */ void SetTlsCaFile(const std::string& path); @@ -456,18 +459,18 @@ namespace ignite bool IsTlsCaFileSet() const; /** - * Get password. + * Get username for SSH host. * - * @return Password. + * @return SSH username. */ const std::string& GetSshUser() const; /** - * Set password. + * Set username for SSH host. * - * @param pass Password. + * @param username SSH username. */ - void SetSshUser(const std::string& user); + void SetSshUser(const std::string& username); /** * Check if the value set. @@ -477,16 +480,16 @@ namespace ignite bool IsSshUserSet() const; /** - * Get password. + * Get hostname for SSH host. * - * @return Password. + * @return SSH hostname. */ const std::string& GetSshHost() const; /** - * Set password. + * Set SSH hostname. * - * @param pass Password. + * @param host SSH hostname. */ void SetSshHost(const std::string& host); @@ -498,16 +501,16 @@ namespace ignite bool IsSshHostSet() const; /** - * Get password. + * Get path to private key file for SSH host. * - * @return Password. + * @return Path to private key file for SSH host. */ const std::string& GetSshPrivateKeyFile () const; /** - * Set password. + * Set path to private key file. * - * @param pass Password. + * @param path Path to private key file for SSH host. */ void SetSshPrivateKeyFile(const std::string& path); @@ -519,16 +522,16 @@ namespace ignite bool IsSshPrivateKeyFileSet() const; /** - * Get password. + * Get SSH private key passphrase. * - * @return Password. + * @return SSH private key passphrase. */ const std::string& GetSshPrivateKeyPassphrase() const; /** - * Set password. + * Set SSH private key file passphrase. * - * @param pass Password. + * @param passphrase SSH private key file passphrase. */ void SetSshPrivateKeyPassphrase(const std::string& passphrase); @@ -540,16 +543,16 @@ namespace ignite bool IsSshPrivateKeyPassphraseSet() const; /** - * Get password. + * Get SSH strict host key checking flag. * - * @return Password. + * @return @true if strict host key checking is enabled. */ bool IsSshStrictHostKeyChecking() const; /** - * Set password. + * Set strict host key checking flag. * - * @param pass Password. + * @param val Value to set. */ void SetSshStrictHostKeyChecking(bool val); @@ -561,16 +564,16 @@ namespace ignite bool IsSshStrictHostKeyCheckingSet() const; /** - * Get password. + * Get path to SSH known hosts file. * - * @return Password. + * @return Path to SSH known hosts file. */ const std::string& GetSshKnownHostsFile() const; /** - * Set password. + * Set path to SSH known hosts file. * - * @param pass Password. + * @param path Path to SSH known hosts file. */ void SetSshKnownHostsFile(const std::string& path); @@ -582,18 +585,18 @@ namespace ignite bool IsSshKnownHostsFileSet() const; /** - * Get password. + * Get scan method. * - * @return Password. + * @return Scan method. */ - const std::string& GetScanMethod() const; + ScanMethod::Type GetScanMethod() const; /** - * Set password. + * Set scan method. * - * @param pass Password. + * @param method Scan method. */ - void SetScanMethod(const std::string& method); + void SetScanMethod(const ScanMethod::Type method); /** * Check if the value set. @@ -603,16 +606,16 @@ namespace ignite bool IsScanMethodSet() const; /** - * Get fetch results page size. + * Get scan limit in # of documents. * - * @return Fetch results page size. + * @return Scan limit. */ int32_t GetScanLimit() const; /** - * Set fetch results page size. + * Set scan limit in # of documents. * - * @param size Fetch results page size. + * @param limit Scan limit in # of documents. */ void SetScanLimit(int32_t limit); @@ -624,18 +627,18 @@ namespace ignite bool IsScanLimitSet() const; /** - * Get password. + * Get schema name to save. * - * @return Password. + * @return Schema name. */ const std::string& GetSchemaName() const; /** - * Set password. + * Set schema name to save. * - * @param pass Password. + * @param name Schema name. */ - void SetSchemaName(const std::string& method); + void SetSchemaName(const std::string& name); /** * Check if the value set. @@ -645,37 +648,37 @@ namespace ignite bool IsSchemaNameSet() const; /** - * Get password. + * Get refresh schema flag. * * @return Password. */ - bool IsSchemaRefresh() const; + bool IsRefreshSchema() const; /** - * Set password. + * Set refresh schema flag. * - * @param pass Password. + * @return @true if the value set. */ - void SetSchemaRefresh(bool val); + void SetRefreshSchema(bool val); /** * Check if the value set. * * @return @true if the value set. */ - bool IsSchemaRefreshSet() const; + bool IsRefreshSchemaSet() const; /** - * Get fetch results page size. + * Get default fetch size. * - * @return Fetch results page size. + * @return Default fetch size. */ int32_t GetDefaultFetchSize() const; /** - * Set fetch results page size. + * Set default fetch size. * - * @param size Fetch results page size. + * @param size Default fetch size. */ void SetDefaultFetchSize(int32_t size); @@ -713,10 +716,10 @@ namespace ignite /** Schema. */ SettableValue database; - /** Server. Deprecated. */ + /** Hostname. */ SettableValue hostname; - /** TCP port. Deprecated. */ + /** Port. */ SettableValue port; /** User. */ @@ -732,7 +735,7 @@ namespace ignite SettableValue loginTimeoutSec; /** Read pereference. */ - SettableValue readPreference; + SettableValue readPreference; /** Replica set name. */ SettableValue replicaSet; @@ -768,7 +771,7 @@ namespace ignite SettableValue sshKnownHostsFile; /** Scan method. */ - SettableValue scanMethod; + SettableValue scanMethod; /** Scan limit. */ SettableValue scanLimit; @@ -800,20 +803,12 @@ namespace ignite const SettableValue& value); template<> - void Configuration::AddToMap(ArgumentMap& map, const std::string& key, - const SettableValue& value); - - template<> - void Configuration::AddToMap< std::vector >(ArgumentMap& map, const std::string& key, - const SettableValue< std::vector >& value); - - template<> - void Configuration::AddToMap(ArgumentMap& map, const std::string& key, - const SettableValue& value); + void Configuration::AddToMap(ArgumentMap& map, const std::string& key, + const SettableValue& value); template<> - void Configuration::AddToMap(ArgumentMap& map, const std::string& key, - const SettableValue& value); + void Configuration::AddToMap(ArgumentMap& map, const std::string& key, + const SettableValue& value); } } } diff --git a/src/odbc/include/ignite/odbc/read_preference.h b/src/odbc/include/ignite/odbc/read_preference.h new file mode 100644 index 000000000..8e522931a --- /dev/null +++ b/src/odbc/include/ignite/odbc/read_preference.h @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace ignite +{ + namespace odbc + { + /** Read Preference enum. */ + struct ReadPreference + { + enum class Type + { + PRIMARY, + + PRIMARY_PREFERRED, + + SECONDARY, + + SECONDARY_PREFERRED, + + NEAREST, + + UNKNOWN + }; + + /** + * Convert preference from string. + * + * @param val String value. + * @param dflt Default value to return on error. + * @return Corresponding enum value. + */ + static Type FromString(const std::string& val, Type dflt = Type::UNKNOWN); + + /** + * Convert mode to string. + * + * @param val Value to convert. + * @return String value. + */ + static std::string ToString(Type val); + + }; + } +} diff --git a/src/odbc/include/ignite/odbc/scan_method.h b/src/odbc/include/ignite/odbc/scan_method.h new file mode 100644 index 000000000..e6d088c91 --- /dev/null +++ b/src/odbc/include/ignite/odbc/scan_method.h @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace ignite +{ + namespace odbc + { + /** Scan method enum. */ + struct ScanMethod + { + enum class Type + { + RANDOM, + + ID_FORWARD, + + ID_REVERSE, + + ALL, + + UNKNOWN + }; + + /** + * Convert preference from string. + * + * @param val String value. + * @param dflt Default value to return on error. + * @return Corresponding enum value. + */ + static Type FromString(const std::string& val, Type dflt = Type::UNKNOWN); + + /** + * Convert mode to string. + * + * @param val Value to convert. + * @return String value. + */ + static std::string ToString(Type val); + + }; + } +} diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index bf4b9cadb..c43d8262e 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -32,7 +32,7 @@ namespace ignite { const std::string Configuration::DefaultValue::dsn = "DocumentDB DSN"; - const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB Driver"; // remove + const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB Driver"; const std::string Configuration::DefaultValue::database = ""; const std::string Configuration::DefaultValue::hostname = ""; const uint16_t Configuration::DefaultValue::port = 27017; @@ -45,7 +45,7 @@ namespace ignite const std::string Configuration::DefaultValue::tlsCaFile = ""; // Schema Generation and Discovery options - const std::string Configuration::DefaultValue::scanMethod = "random"; + const ScanMethod::Type Configuration::DefaultValue::scanMethod = ScanMethod::Type::RANDOM; const int32_t Configuration::DefaultValue::scanLimit = 1000; const std::string Configuration::DefaultValue::schemaName = "_default"; const bool Configuration::DefaultValue::refreshSchema = false; @@ -61,7 +61,7 @@ namespace ignite // Additional options const std::string Configuration::DefaultValue::appName = "Amazon DocumentDB ODBC Driver"; const int32_t Configuration::DefaultValue::loginTimeoutSec = 0; - const std::string Configuration::DefaultValue::readPreference = "primary"; + const ReadPreference::Type Configuration::DefaultValue::readPreference = ReadPreference::Type::PRIMARY; const std::string Configuration::DefaultValue::replicaSet = ""; const bool Configuration::DefaultValue::retryReads = true; const int32_t Configuration::DefaultValue::defaultFetchSize = 2000; @@ -132,9 +132,9 @@ namespace ignite return port.GetValue(); } - void Configuration::SetTcpPort(uint16_t port) + void Configuration::SetTcpPort(uint16_t portNumber) { - this->port.SetValue(port); + this->port.SetValue(portNumber); } bool Configuration::IsTcpPortSet() const @@ -155,9 +155,9 @@ namespace ignite return dsn.IsSet(); } - void Configuration::SetDsn(const std::string& dsn) + void Configuration::SetDsn(const std::string& dsnName) { - this->dsn.SetValue(dsn); + this->dsn.SetValue(dsnName); } const std::string& Configuration::GetDriver() const @@ -165,9 +165,9 @@ namespace ignite return driver.GetValue(); } - void Configuration::SetDriver(const std::string& driver) + void Configuration::SetDriver(const std::string& driverName) { - this->driver.SetValue(driver); + this->driver.SetValue(driverName); } const std::string& Configuration::GetHostname() const @@ -230,12 +230,12 @@ namespace ignite return loginTimeoutSec.IsSet(); } - const std::string& Configuration::GetReadPreference() const + ReadPreference::Type Configuration::GetReadPreference() const { return readPreference.GetValue(); } - void Configuration::SetReadPreference(const std::string& preference) + void Configuration::SetReadPreference(const ReadPreference::Type preference) { this->readPreference.SetValue(preference); } @@ -340,9 +340,9 @@ namespace ignite return sshHost.GetValue(); } - void Configuration::SetSshHost(const std::string& hostname) + void Configuration::SetSshHost(const std::string& host) { - this->sshHost.SetValue(hostname); + this->sshHost.SetValue(host); } bool Configuration::IsSshHostSet() const @@ -410,12 +410,12 @@ namespace ignite return sshKnownHostsFile.IsSet(); } - const std::string& Configuration::GetScanMethod() const + ScanMethod::Type Configuration::GetScanMethod() const { return scanMethod.GetValue(); } - void Configuration::SetScanMethod(const std::string& method) + void Configuration::SetScanMethod(const ScanMethod::Type method) { this->scanMethod.SetValue(method); } @@ -455,17 +455,17 @@ namespace ignite return schemaName.IsSet(); } - bool Configuration::IsSchemaRefresh() const + bool Configuration::IsRefreshSchema() const { return refreshSchema.GetValue(); } - void Configuration::SetSchemaRefresh(bool val) + void Configuration::SetRefreshSchema(bool val) { this->refreshSchema.SetValue(val); } - bool Configuration::IsSchemaRefreshSet() const + bool Configuration::IsRefreshSchemaSet() const { return refreshSchema.IsSet(); } @@ -475,9 +475,9 @@ namespace ignite return user.GetValue(); } - void Configuration::SetUser(const std::string& user) + void Configuration::SetUser(const std::string& username) { - this->user.SetValue(user); + this->user.SetValue(username); } bool Configuration::IsUserSet() const @@ -517,7 +517,6 @@ namespace ignite void Configuration::ToMap(ArgumentMap& res) const { - // Need to add properties here!! AddToMap(res, ConnectionStringParser::Key::dsn, dsn); AddToMap(res, ConnectionStringParser::Key::driver, driver); AddToMap(res, ConnectionStringParser::Key::database, database); @@ -578,35 +577,20 @@ namespace ignite template<> void Configuration::AddToMap(ArgumentMap& map, const std::string& key, - const SettableValue& value) + const SettableValue& value) { if (value.IsSet()) - map[key] = value.GetValue().ToString(); + map[key] = ReadPreference::ToString(value.GetValue()); } template<> void Configuration::AddToMap(ArgumentMap& map, const std::string& key, - const SettableValue< std::vector >& value) + const SettableValue& value) { if (value.IsSet()) - map[key] = AddressesToString(value.GetValue()); + map[key] = ScanMethod::ToString(value.GetValue()); } - template<> - void Configuration::AddToMap(ArgumentMap& map, const std::string& key, - const SettableValue& value) - { - if (value.IsSet()) - map[key] = ssl::SslMode::ToString(value.GetValue()); - } - - template<> - void Configuration::AddToMap(ArgumentMap& map, const std::string& key, - const SettableValue& value) - { - if (value.IsSet()) - map[key] = NestedTxMode::ToString(value.GetValue()); - } } } } diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index 489fa624c..1a8997174 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -258,7 +258,20 @@ namespace ignite } else if (lKey == Key::readPreference) { - cfg.SetReadPreference(value); + ReadPreference::Type preference = ReadPreference::FromString(value); + + if (preference == ReadPreference::Type::UNKNOWN) + { + if (diag) + { + diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, + "Specified read preference is not supported. Default value used ('primary')."); + } + + return; + } + + cfg.SetReadPreference(preference); } else if (lKey == Key::replicaSet) { @@ -358,7 +371,20 @@ namespace ignite } else if (lKey == Key::scanMethod) { - cfg.SetScanMethod(value); + ScanMethod::Type method = ScanMethod::FromString(value); + + if (method == ScanMethod::Type::UNKNOWN) + { + if (diag) + { + diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, + "Specified scan method is not supported. Default value used ('random')."); + } + + return; + } + + cfg.SetScanMethod(method); } else if (lKey == Key::scanLimit) { @@ -413,7 +439,7 @@ namespace ignite return; } - cfg.SetSchemaRefresh(res == BoolParseResult::AI_TRUE); + cfg.SetRefreshSchema(res == BoolParseResult::AI_TRUE); } else if (lKey == Key::defaultFetchSize) { diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 564d6b272..c9fd4a0fb 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -142,7 +142,10 @@ namespace ignite SettableValue readPreference = ReadDsnString(dsn, ConnectionStringParser::Key::readPreference); if (readPreference.IsSet() && !config.IsReadPreferenceSet()) - config.SetReadPreference(readPreference.GetValue()); + { + ReadPreference::Type preference = ReadPreference::FromString(readPreference.GetValue(), ReadPreference::Type::PRIMARY); + config.SetReadPreference(preference); + } SettableValue replicaSet = ReadDsnString(dsn, ConnectionStringParser::Key::replicaSet); @@ -202,7 +205,10 @@ namespace ignite SettableValue scanMethod = ReadDsnString(dsn, ConnectionStringParser::Key::scanMethod); if (scanMethod.IsSet() && !config.IsScanMethodSet()) - config.SetScanMethod(scanMethod.GetValue()); + { + ScanMethod::Type method = ScanMethod::FromString(scanMethod.GetValue(), ScanMethod::Type::RANDOM); + config.SetScanMethod(method); + } SettableValue scanLimit = ReadDsnInt(dsn, ConnectionStringParser::Key::scanLimit); @@ -217,8 +223,8 @@ namespace ignite SettableValue refreshSchema = ReadDsnBool(dsn, ConnectionStringParser::Key::refreshSchema); - if (refreshSchema.IsSet() && !config.IsSchemaRefreshSet()) - config.SetSchemaRefresh(refreshSchema.GetValue()); + if (refreshSchema.IsSet() && !config.IsRefreshSchemaSet()) + config.SetRefreshSchema(refreshSchema.GetValue()); SettableValue defaultFetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::defaultFetchSize); diff --git a/src/odbc/src/read_preference.cpp b/src/odbc/src/read_preference.cpp new file mode 100644 index 000000000..43d81c4dc --- /dev/null +++ b/src/odbc/src/read_preference.cpp @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ignite/odbc/read_preference.h" + +namespace ignite +{ + namespace odbc + { + ReadPreference::Type ReadPreference::FromString(const std::string& val, Type dflt) + { + std::string lowerVal = common::ToLower(val); + + common::StripSurroundingWhitespaces(lowerVal); + + if (lowerVal == "primary") + return ReadPreference::Type::PRIMARY; + + if (lowerVal == "primary_preferred") + return ReadPreference::Type::PRIMARY_PREFERRED; + + if (lowerVal == "secondary") + return ReadPreference::Type::SECONDARY; + + if (lowerVal == "secondary_preferred") + return ReadPreference::Type::SECONDARY_PREFERRED; + + if (lowerVal == "nearest") + return ReadPreference::Type::NEAREST; + + return dflt; + } + + std::string ReadPreference::ToString(Type val) + { + switch (val) + { + case ReadPreference::Type::PRIMARY: + return "primary"; + + case ReadPreference::Type::PRIMARY_PREFERRED: + return "primary_preferred"; + + case ReadPreference::Type::SECONDARY: + return "secondary"; + + case ReadPreference::Type::SECONDARY_PREFERRED: + return "secondary_preferred"; + + case ReadPreference::Type::NEAREST: + return "nearest"; + + default: + return "unknown"; + } + } + } +} diff --git a/src/odbc/src/scan_method.cpp b/src/odbc/src/scan_method.cpp new file mode 100644 index 000000000..06400dd9a --- /dev/null +++ b/src/odbc/src/scan_method.cpp @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ignite/odbc/scan_method.h" + +namespace ignite +{ + namespace odbc + { + ScanMethod::Type ScanMethod::FromString(const std::string& val, Type dflt) + { + std::string lowerVal = common::ToLower(val); + + common::StripSurroundingWhitespaces(lowerVal); + + if (lowerVal == "random") + return ScanMethod::Type::RANDOM; + + if (lowerVal == "id_forward") + return ScanMethod::Type::ID_FORWARD; + + if (lowerVal == "id_reverse") + return ScanMethod::Type::ID_REVERSE; + + if (lowerVal == "all") + return ScanMethod::Type::ALL; + + return dflt; + } + + std::string ScanMethod::ToString(Type val) + { + switch (val) + { + case ScanMethod::Type::ID_FORWARD: + return "id_forward"; + + case ScanMethod::Type::ID_REVERSE: + return "id_reverse"; + + case ScanMethod::Type::ALL: + return "all"; + + case ScanMethod::Type::RANDOM: + return "random"; + + default: + return "unknown"; + } + } + } +} From de1606c6c61ac5d4b054e0fc8aa5e4c987b5c136 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Thu, 20 Jan 2022 09:27:13 -0800 Subject: [PATCH 025/165] Remove extra file --- src/odbc-test/CMakeLists.txt.bak | 113 ------------------------------- 1 file changed, 113 deletions(-) delete mode 100644 src/odbc-test/CMakeLists.txt.bak diff --git a/src/odbc-test/CMakeLists.txt.bak b/src/odbc-test/CMakeLists.txt.bak deleted file mode 100644 index 0d30d5356..000000000 --- a/src/odbc-test/CMakeLists.txt.bak +++ /dev/null @@ -1,113 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -project(ignite-odbc-tests) - -set(TARGET ${PROJECT_NAME}) - -if (WIN32) - set(Boost_USE_STATIC_LIBS ON) -endif() - -find_package(Boost 1.53 REQUIRED COMPONENTS unit_test_framework chrono thread system regex) - -find_package(ODBC REQUIRED) - -include_directories(SYSTEM ${ODBC_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${JNI_INCLUDE_DIRS}) -include_directories(include ../odbc/include ../network/include) - -set(SOURCES - src/dummy_test.cpp - src/configuration_test.cpp -# TODO uncomment/rework the tests after get some connectivity and functionalities working. -# src/teamcity/teamcity_boost.cpp -# src/teamcity/teamcity_messages.cpp -# src/parser_test.cpp -# src/cursor_test.cpp -# src/connection_info_test.cpp -# src/connection_test.cpp -# src/application_data_buffer_test.cpp -# src/column_test.cpp -# src/configuration_test.cpp -# src/row_test.cpp -# src/meta_queries_test.cpp -# src/utility_test.cpp -# src/queries_test.cpp -# src/queries_ssl_test.cpp -# src/test_utils.cpp -# src/sql_test_suite_fixture.cpp -# src/sql_string_functions_test.cpp -# src/sql_numeric_functions_test.cpp -# src/sql_aggregate_functions_test.cpp -# src/sql_system_functions_test.cpp -# src/sql_esc_convert_function_test.cpp -# src/sql_operators_test.cpp -# src/sql_value_expressions_test.cpp -# src/sql_types_test.cpp -# src/sql_date_time_functions_test.cpp -# src/sql_outer_join_test.cpp -# src/sql_get_info_test.cpp -# src/api_robustness_test.cpp -# src/attributes_test.cpp -# src/errors_test.cpp -# src/odbc_test_suite.cpp -# src/types_test.cpp -# src/transaction_test.cpp -# src/authentication_test.cpp -# src/sql_parsing_test.cpp -# src/streaming_test.cpp -# src/cursor_binding_test.cpp -# src/test_server.cpp -# ../odbc/src/log.cpp -# ../odbc/src/cursor.cpp -# ../odbc/src/diagnostic/diagnostic_record.cpp -# ../odbc/src/diagnostic/diagnostic_record_storage.cpp -# ../odbc/src/config/config_tools.cpp -# ../odbc/src/config/configuration.cpp -# ../odbc/src/config/connection_info.cpp -# ../odbc/src/config/connection_string_parser.cpp -# ../odbc/src/app/application_data_buffer.cpp -# ../odbc/src/ssl_mode.cpp -# ../odbc/src/sql/sql_parser.cpp -# ../odbc/src/sql/sql_lexer.cpp -# ../odbc/src/sql/sql_set_streaming_command.cpp -# ../odbc/src/sql/sql_utils.cpp -# ../odbc/src/row.cpp -# ../odbc/src/protocol_version.cpp -# ../odbc/src/column.cpp -# ../odbc/src/common_types.cpp -# ../odbc/src/utility.cpp -# ../odbc/src/result_page.cpp -# ../odbc/src/nested_tx_mode.cpp - ) - -add_executable(${TARGET} ${SOURCES}) - -target_link_libraries(${TARGET} ${Boost_LIBRARIES} ignite ${ODBC_LIBRARY}) -target_code_coverage(${TARGET} PUBLIC AUTO ALL) - -if (WIN32) - remove_definitions(-DUNICODE=1) -else() - add_definitions(-DBOOST_TEST_DYN_LINK) -endif() - -set(TEST_TARGET IgniteOdbcTest) - -add_test(NAME ${TEST_TARGET} COMMAND ${TARGET} --catch_system_errors=no --log_level=all) - -set_tests_properties(${TEST_TARGET} PROPERTIES ENVIRONMENT IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH=${PROJECT_SOURCE_DIR}/config) From c2f744ae0ff941a321c12acb62a437d665bc89f3 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 09:31:11 -0800 Subject: [PATCH 026/165] [AD-522] Add small letter case to keep format consistency in dsn_configuration_window.h Add small letter case to keep format consistency in dsn_configuration_window.h fixed one typo (Create authentication settings group box) --- .../odbc/system/ui/dsn_configuration_window.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 5779ee7bf..33c18ba41 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -176,7 +176,7 @@ namespace ignite int CreateConnectionSettingsGroup(int posX, int posY, int sizeX); /** - * Create aythentication settings group box. + * Create authentication settings group box. * * @param posX X position. * @param posY Y position. @@ -259,13 +259,13 @@ namespace ignite /** Read preference label. */ std::auto_ptr readPreferenceLabel; - /** Replica Set edit. */ + /** Replica set edit. */ std::auto_ptr< Window > replicaSetEdit; - /** Replica Set label. */ + /** Replica set label. */ std::auto_ptr< Window > replicaSetLabel; - /** Retry reads CheckBox. */ + /** Retry reads checkBox. */ std::auto_ptr retryReadsCheckBox; /** Fetch size edit. */ @@ -286,16 +286,16 @@ namespace ignite /** Cancel button. */ std::auto_ptr cancelButton; - /** TLS Encryption CheckBox. */ + /** TLS encryption checkBox. */ std::auto_ptr tlsCheckBox; - /** TLS Allow Invalid Hostnames CheckBox. */ + /** TLS allow invalid hostnames checkBox. */ std::auto_ptr tlsAllowInvalidHostnamesCheckBox; - /** TLS Certificate Authority File label. */ + /** TLS certificate authority file label. */ std::auto_ptr tlsCaFileLabel; - /** TLS Certificate Authority File edit. */ + /** TLS certificate authority file edit. */ std::auto_ptr tlsCaFileEdit; /** User label. */ From 68ab4b96158531572dc7828b940b240235ff88f1 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Thu, 20 Jan 2022 10:28:32 -0800 Subject: [PATCH 027/165] Remove redundant declaration --- src/odbc-test/CMakeLists.txt | 2 +- src/odbc/CMakeLists.txt | 2 +- .../odbc/config/connection_string_parser.h | 11 +----- .../include/ignite/odbc/read_preference.h | 38 +++++++++---------- src/odbc/include/ignite/odbc/scan_method.h | 36 +++++++++--------- .../src/config/connection_string_parser.cpp | 2 +- 6 files changed, 41 insertions(+), 50 deletions(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 96276e8e3..f81e1a103 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -32,7 +32,7 @@ include_directories(include ../odbc/include ../network/include) set(SOURCES src/dummy_test.cpp - src/configuration_test.cpp + src/configuration_test.cpp ../odbc/src/config/config_tools.cpp ../odbc/src/config/configuration.cpp ../odbc/src/config/connection_info.cpp diff --git a/src/odbc/CMakeLists.txt b/src/odbc/CMakeLists.txt index 522dd1392..e2021f3e7 100644 --- a/src/odbc/CMakeLists.txt +++ b/src/odbc/CMakeLists.txt @@ -70,7 +70,7 @@ set(SOURCES src/app/application_data_buffer.cpp src/utility.cpp src/log.cpp src/read_preference.cpp - src/scan_method.cpp) + src/scan_method.cpp) if (WIN32) include_directories(os/win/include) diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index 27e4f48d2..f88411c7e 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -119,7 +119,7 @@ namespace ignite /** Connection attribute keyword for protocol version attribute. */ static const std::string protocolVersion; - /** Connection attribute keyword for fetch results page size attribute. */ + /** Connection attribute keyword for defaultFetchSize attribute. */ static const std::string defaultFetchSize; /** Connection attribute keyword for sslMode attribute. */ @@ -134,20 +134,11 @@ namespace ignite /** Connection attribute keyword for sslCaFile attribute. */ static const std::string sslCaFile; - /** Connection attribute keyword for username attribute. */ - static const std::string user; - - /** Connection attribute keyword for password attribute. */ - static const std::string password; - /** Connection attribute keyword for username attribute. */ static const std::string uid; /** Connection attribute keyword for password attribute. */ static const std::string pwd; - - /** Connection attribute keyword for nestedTxMode attribute. */ - static const std::string nestedTxMode; }; /** diff --git a/src/odbc/include/ignite/odbc/read_preference.h b/src/odbc/include/ignite/odbc/read_preference.h index 8e522931a..2859692b9 100644 --- a/src/odbc/include/ignite/odbc/read_preference.h +++ b/src/odbc/include/ignite/odbc/read_preference.h @@ -21,7 +21,7 @@ namespace ignite { namespace odbc { - /** Read Preference enum. */ + /** Read Preference enum. */ struct ReadPreference { enum class Type @@ -38,24 +38,24 @@ namespace ignite UNKNOWN }; - - /** - * Convert preference from string. - * - * @param val String value. - * @param dflt Default value to return on error. - * @return Corresponding enum value. - */ - static Type FromString(const std::string& val, Type dflt = Type::UNKNOWN); - - /** - * Convert mode to string. - * - * @param val Value to convert. - * @return String value. - */ - static std::string ToString(Type val); + + /** + * Convert preference from string. + * + * @param val String value. + * @param dflt Default value to return on error. + * @return Corresponding enum value. + */ + static Type FromString(const std::string& val, Type dflt = Type::UNKNOWN); + + /** + * Convert mode to string. + * + * @param val Value to convert. + * @return String value. + */ + static std::string ToString(Type val); - }; + }; } } diff --git a/src/odbc/include/ignite/odbc/scan_method.h b/src/odbc/include/ignite/odbc/scan_method.h index e6d088c91..1feb2f9ca 100644 --- a/src/odbc/include/ignite/odbc/scan_method.h +++ b/src/odbc/include/ignite/odbc/scan_method.h @@ -21,7 +21,7 @@ namespace ignite { namespace odbc { - /** Scan method enum. */ + /** Scan method enum. */ struct ScanMethod { enum class Type @@ -36,24 +36,24 @@ namespace ignite UNKNOWN }; - - /** - * Convert preference from string. - * - * @param val String value. - * @param dflt Default value to return on error. - * @return Corresponding enum value. - */ - static Type FromString(const std::string& val, Type dflt = Type::UNKNOWN); + + /** + * Convert scan method from string. + * + * @param val String value. + * @param dflt Default value to return on error. + * @return Corresponding enum value. + */ + static Type FromString(const std::string& val, Type dflt = Type::UNKNOWN); - /** - * Convert mode to string. - * - * @param val Value to convert. - * @return String value. - */ - static std::string ToString(Type val); + /** + * Convert method to string. + * + * @param val Value to convert. + * @return String value. + */ + static std::string ToString(Type val); - }; + }; } } diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index 1a8997174..96ba6b58d 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -142,7 +142,7 @@ namespace ignite diagnostic::DiagnosticRecordStorage* diag) { std::string lKey = common::ToLower(key); - + if (lKey == Key::dsn) { cfg.SetDsn(value); From 9c52daf5c7ccd3bd9640e9618cdc965be80f1bbb Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 14:02:01 -0800 Subject: [PATCH 028/165] [AD-522] add variable definitions for SSH tunnel settings for config UI --- .../odbc/system/ui/dsn_configuration_window.h | 62 ++++++++++++++++++- .../system/ui/dsn_configuration_window.cpp | 18 ++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 33c18ba41..e17d0270c 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -42,6 +42,7 @@ namespace ignite enum Type { CONNECTION_SETTINGS_GROUP_BOX = 100, + SSH_SETTINGS_GROUP_BOX, SSL_SETTINGS_GROUP_BOX, ADDITIONAL_SETTINGS_GROUP_BOX, AUTH_SETTINGS_GROUP_BOX, @@ -51,6 +52,17 @@ namespace ignite ADDRESS_LABEL, SCHEMA_EDIT, SCHEMA_LABEL, + SSH_USER_EDIT, + SSH_USER_LABEL, + SSH_HOST_EDIT, + SSH_HOST_LABEL, + SSH_PRIVATE_KEY_FILE_EDIT, + SSH_PRIVATE_KEY_FILE_LABEL, + SSH_PRIVATE_KEY_PASSPHRASE_EDIT, + SSH_PRIVATE_KEY_PASSPHRASE_LABEL, + SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX, + SSH_KNOWN_HOSTS_FILE_EDIT, + SSH_KNOWN_HOSTS_FILE_LABEL, APP_NAME_EDIT, APP_NAME_LABEL, LOGIN_TIMEOUT_SEC_EDIT, @@ -185,6 +197,16 @@ namespace ignite */ int CreateAuthSettingsGroup(int posX, int posY, int sizeX); + /** + * Create internal SSH tunnel settings group box. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreateSshSettingsGroup(int posX, int posY, int sizeX); + /** * Create SSL settings group box. * @@ -214,6 +236,9 @@ namespace ignite /** Connection settings group box. */ std::auto_ptr connectionSettingsGroupBox; + /** SSH settings group box. */ + std::auto_ptr sshSettingsGroupBox; + /** SSL settings group box. */ std::auto_ptr sslSettingsGroupBox; @@ -241,6 +266,39 @@ namespace ignite /** DSN schema edit field. */ std::auto_ptr schemaEdit; + /** SSH user edit. */ + std::auto_ptr sshUserEdit; + + /** SSH user label. */ + std::auto_ptr sshUserLabel; + + /** SSH host edit. */ + std::auto_ptr sshHostEdit; + + /** SSH host label. */ + std::auto_ptr sshHostLabel; + + /** SSH private key file edit. */ + std::auto_ptr sshPrivateKeyFileEdit; + + /** SSH private key file label. */ + std::auto_ptr sshPrivateKeyFileLabel; + + /** SSH private key passphrase edit. */ + std::auto_ptr sshPrivateKeyPassphraseEdit; + + /** SSH private key passphrase label. */ + std::auto_ptr sshPrivateKeyPassphraseLabel; + + /** SSH strict host key checking checkBox. */ + std::auto_ptr sshStrictHostKeyCheckingCheckBox; + + /** SSH known host file edit. */ + std::auto_ptr sshKnownHostsFileEdit; + + /** SSH know host file label. */ + std::auto_ptr sshKnownHostsFileLabel; + /** Application name edit. */ std::auto_ptr appNameEdit; @@ -260,10 +318,10 @@ namespace ignite std::auto_ptr readPreferenceLabel; /** Replica set edit. */ - std::auto_ptr< Window > replicaSetEdit; + std::auto_ptr replicaSetEdit; /** Replica set label. */ - std::auto_ptr< Window > replicaSetLabel; + std::auto_ptr replicaSetLabel; /** Retry reads checkBox. */ std::auto_ptr retryReadsCheckBox; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 9a9f7e66d..3d6885f44 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -48,6 +48,19 @@ namespace ignite addressEdit(), schemaLabel(), schemaEdit(), + // internal SSH tunnel vars + sshUserLabel(), + sshUserEdit(), + sshHostLabel(), + sshHostEdit(), + sshPrivateKeyFileLabel(), + sshPrivateKeyFileEdit(), + sshPrivateKeyPassphraseLabel(), + sshPrivateKeyPassphraseEdit(), + sshStrictHostKeyCheckingCheckBox(), + sshKnownHostsFileLabel(), + sshKnownHostsFileEdit(), + // end of SSH vars appNameLabel(), appNameEdit(), readPreferenceLabel(), @@ -109,6 +122,7 @@ namespace ignite groupPosY += INTERVAL + CreateConnectionSettingsGroup(MARGIN, groupPosY, groupSizeY); groupPosY += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosY, groupSizeY); + groupPosY += INTERVAL + CreateSshSettingsGroup(MARGIN, groupPosY, groupSizeY); groupPosY += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosY, groupSizeY); groupPosY += INTERVAL + CreateAdditionalSettingsGroup(MARGIN, groupPosY, groupSizeY); // test: if above code is commented out, additional settings shouldn't appear in config window. Result: Yes test success. @@ -220,6 +234,10 @@ namespace ignite return rowPos - posY; } + int DsnConfigurationWindow::CreateSshSettingsGroup(int posX, int posY, int sizeX) + { + } + int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) { // TODO: rename function name from Ssl to TLS after UI works From 07de6efed0b335f229809e4e4b1dda4fefa0acd4 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 14:03:42 -0800 Subject: [PATCH 029/165] [AD-522] add function definition for SSH Tunnel added SSH User, SSH Host. SSH Strict Host Key Checking, and SSH Known Hosts File onto the UI. However, the code to save the written values would be done in later commits. --- .../system/ui/dsn_configuration_window.cpp | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 3d6885f44..4c156b873 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -236,6 +236,53 @@ namespace ignite int DsnConfigurationWindow::CreateSshSettingsGroup(int posX, int posY, int sizeX) { + enum { LABEL_WIDTH = 120 }; // -AL- copied from above function + + int labelPosX = posX + INTERVAL; + + int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + + int rowPos = posY + 2 * INTERVAL; + + int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; + + const char* val = config.GetSshUser().c_str(); + + sshUserLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSH user :", ChildId::SSH_USER_LABEL); + sshUserEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_USER_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetSshHost().c_str(); + + sshHostLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "SSH host :", ChildId::SSH_HOST_LABEL); + sshHostEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, ChildId::SSH_HOST_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + sshStrictHostKeyCheckingCheckBox = CreateCheckBox( + labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "SSH strict host key checking", + ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX, config.IsSshStrictHostKeyChecking()); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetSshKnownHostsFile().c_str(); + + sshKnownHostsFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "SSH known hosts:", ChildId::SSH_KNOWN_HOSTS_FILE_LABEL); + sshKnownHostsFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, + ChildId::SSH_KNOWN_HOST_FILE_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + sshSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "Internal SSH Tunnel settings", + ChildId::SSH_SETTINGS_GROUP_BOX); + + return rowPos - posY; } int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) From f2e92a497c072b83e5ec9873e94e7a7e5710f06d Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 14:04:54 -0800 Subject: [PATCH 030/165] [AD-522] code draft for configuration.cpp add draft variable definition to Enable ssh tunnel boolean value --- src/odbc/src/config/configuration.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index a0d11bc0b..8fe0e7567 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -45,13 +45,14 @@ namespace ignite const bool Configuration::DefaultValue::tlsAllowInvalidHostnames = false; // needs to be set to true for SSH; TLS Allow Invalid Hostnames const std::string Configuration::DefaultValue::tlsCaFile = ""; //renamed from SSL CA file - // Schema Generation and Discovery options // need to add to UI // I think I need a new group setting thing + // Schema Generation and Discovery options // need to add to UI // I think I need a new group setting function const std::string Configuration::DefaultValue::scanMethod = "random"; const int32_t Configuration::DefaultValue::scanLimit = 1000; const std::string Configuration::DefaultValue::schemaName = "_default"; const bool Configuration::DefaultValue::refreshSchema = false; // Internal SSH Tunnel options // need to add to UI + // const bool Configuration::DefaultValue::sshEnable = false; const std::string Configuration::DefaultValue::sshUser = ""; const std::string Configuration::DefaultValue::sshHost = ""; const std::string Configuration::DefaultValue::sshPrivateKeyFile = ""; From fbaa1033fd3ec3b06749e739a3ab284f8c634ecd Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 14:20:41 -0800 Subject: [PATCH 031/165] Revert "change defaultFetchSize to fetchSize in configuration.h" This reverts commit f311e3bc7df1fd66d7be66c8e60170a41d078c18. --- .../include/ignite/odbc/config/configuration.h | 10 +++++----- src/odbc/src/config/configuration.cpp | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index 695f257e7..c5a021c2d 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -137,7 +137,7 @@ namespace ignite // static const ProtocolVersion& protocolVersion; /** Default value for fetch results page size attribute. */ - static const int32_t fetchSize; + static const int32_t defaultFetchSize; /** Default value for nestedTxMode attribute. */ static const NestedTxMode::Type nestedTxMode; @@ -703,21 +703,21 @@ namespace ignite * * @return Fetch results page size. */ - int32_t GetFetchSize() const; + int32_t GetDefaultFetchSize() const; /** * Set fetch results page size. * * @param size Fetch results page size. */ - void SetFetchSize(int32_t size); + void SetDefaultFetchSize(int32_t size); /** * Check if the value set. * * @return @true if the value set. */ - bool IsFetchSizeSet() const; + bool IsDefaultFetchSizeSet() const; /** * Get argument map. @@ -816,7 +816,7 @@ namespace ignite SettableValue refreshSchema; /** Request and response page size. */ - SettableValue fetchSize; + SettableValue defaultFetchSize; }; template<> diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 8fe0e7567..50aedf5c7 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -66,7 +66,7 @@ namespace ignite const std::string Configuration::DefaultValue::readPreference = ""; const std::string Configuration::DefaultValue::replicaSet = ""; const bool Configuration::DefaultValue::retryReads = true; - const int32_t Configuration::DefaultValue::fetchSize = 2000; + const int32_t Configuration::DefaultValue::defaultFetchSize = 2000; const NestedTxMode::Type Configuration::DefaultValue::nestedTxMode = NestedTxMode::AI_ERROR; // remove @@ -97,7 +97,7 @@ namespace ignite scanLimit(DefaultValue::scanLimit), schemaName(DefaultValue::schemaName), refreshSchema(DefaultValue::refreshSchema), - fetchSize(DefaultValue::fetchSize) + defaultFetchSize(DefaultValue::defaultFetchSize) { // No-op. } @@ -520,19 +520,19 @@ namespace ignite return password.IsSet(); } - int32_t Configuration::GetFetchSize() const + int32_t Configuration::GetDefaultFetchSize() const { - return fetchSize.GetValue(); + return defaultFetchSize.GetValue(); } - void Configuration::SetFetchSize(int32_t size) + void Configuration::SetDefaultFetchSize(int32_t size) { - this->fetchSize.SetValue(size); + this->defaultFetchSize.SetValue(size); } - bool Configuration::IsFetchSizeSet() const + bool Configuration::IsDefaultFetchSizeSet() const { - return fetchSize.IsSet(); + return defaultFetchSize.IsSet(); } void Configuration::ToMap(ArgumentMap& res) const @@ -564,7 +564,7 @@ namespace ignite AddToMap(res, ConnectionStringParser::Key::scanLimit, scanLimit); AddToMap(res, ConnectionStringParser::Key::schemaName, schemaName); AddToMap(res, ConnectionStringParser::Key::refreshSchema, refreshSchema); - AddToMap(res, ConnectionStringParser::Key::fetchSize, fetchSize); + AddToMap(res, ConnectionStringParser::Key::defaultFetchSize, defaultFetchSize); } template<> From 124b7256d8f96fb31363aa2efb0423b115b11b0a Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 14:21:28 -0800 Subject: [PATCH 032/165] Revert "[AD-522] bugfix - change DefaultFetchSize to fetchSize in all related files to be consistent with configuration.h" This reverts commit 2bcd2a492bd69fbde5de986a03c5a407a729ba47. --- .../ignite/odbc/config/connection_string_parser.h | 2 +- src/odbc/src/config/connection_string_parser.cpp | 6 +++--- src/odbc/src/dsn_config.cpp | 10 +++++----- src/odbc/src/query/batch_query.cpp | 2 +- src/odbc/src/query/data_query.cpp | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index ba557d6c3..27e4f48d2 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -120,7 +120,7 @@ namespace ignite static const std::string protocolVersion; /** Connection attribute keyword for fetch results page size attribute. */ - static const std::string fetchSize; + static const std::string defaultFetchSize; /** Connection attribute keyword for sslMode attribute. */ static const std::string sslMode; diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index a05e2a530..308bb225b 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -57,7 +57,7 @@ namespace ignite const std::string ConnectionStringParser::Key::scanLimit = "scan_limit"; const std::string ConnectionStringParser::Key::schemaName = "schema_name"; const std::string ConnectionStringParser::Key::refreshSchema = "refresh_schema"; - const std::string ConnectionStringParser::Key::fetchSize = "fetch_size"; + const std::string ConnectionStringParser::Key::defaultFetchSize = "default_fetch_size"; const std::string ConnectionStringParser::Key::uid = "uid"; const std::string ConnectionStringParser::Key::pwd = "pwd"; @@ -399,7 +399,7 @@ namespace ignite cfg.SetTls(res == BoolParseResult::AI_TRUE); } - else if (lKey == Key::fetchSize) + else if (lKey == Key::defaultFetchSize) { if (!common::AllDigits(value)) { @@ -443,7 +443,7 @@ namespace ignite return; } - cfg.SetFetchSize(static_cast(numValue)); + cfg.SetDefaultFetchSize(static_cast(numValue)); } else if (lKey == Key::tlsCaFile) { diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 9b02548ed..6526a38bd 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -219,7 +219,7 @@ namespace ignite if (scanLimit.IsSet() && !config.IsScanLimitSet() && scanLimit.GetValue() > 0) - config.SetFetchSize(scanLimit.GetValue()); + config.SetDefaultFetchSize(scanLimit.GetValue()); SettableValue schemaName = ReadDsnString(dsn, ConnectionStringParser::Key::schemaName); @@ -231,11 +231,11 @@ namespace ignite if (refreshSchema.IsSet() && !config.IsSchemaRefreshSet()) config.SetSchemaRefresh(refreshSchema.GetValue()); - SettableValue fetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::fetchSize); + SettableValue defaultFetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::defaultFetchSize); - if (fetchSize.IsSet() && !config.IsFetchSizeSet() - && fetchSize.GetValue() > 0) - config.SetFetchSize(fetchSize.GetValue()); + if (defaultFetchSize.IsSet() && !config.IsDefaultFetchSizeSet() + && defaultFetchSize.GetValue() > 0) + config.SetDefaultFetchSize(defaultFetchSize.GetValue()); } } } diff --git a/src/odbc/src/query/batch_query.cpp b/src/odbc/src/query/batch_query.cpp index 6a82d690e..7390b4f59 100644 --- a/src/odbc/src/query/batch_query.cpp +++ b/src/odbc/src/query/batch_query.cpp @@ -52,7 +52,7 @@ namespace ignite if (executed) Close(); - int32_t maxPageSize = connection.GetConfiguration().GetFetchSize(); + int32_t maxPageSize = connection.GetConfiguration().GetDefaultFetchSize(); int32_t rowNum = params.GetParamSetSize(); SqlResult::Type res; diff --git a/src/odbc/src/query/data_query.cpp b/src/odbc/src/query/data_query.cpp index 28a9ab72f..d5c4d6a6d 100644 --- a/src/odbc/src/query/data_query.cpp +++ b/src/odbc/src/query/data_query.cpp @@ -193,7 +193,7 @@ namespace ignite if (affected >= 0) return affected; - return connection.GetConfiguration().GetFetchSize(); + return connection.GetConfiguration().GetDefaultFetchSize(); } SqlResult::Type DataQuery::NextResultSet() @@ -320,7 +320,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetFetchSize()); + QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); QueryFetchResponse rsp(*resultPage); try @@ -361,7 +361,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetFetchSize()); + QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); QueryMoreResultsResponse rsp(*resultPage); try From 1ce78789f90f2dee83c4bde19ef4dd9a0dfa4639 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Thu, 20 Jan 2022 14:27:33 -0800 Subject: [PATCH 033/165] [AD-517] * Change the C++ version to use to compile. --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d996aafd9..dc04f9fda 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,7 +21,7 @@ project(Ignite.C++ VERSION 2.13.0.58917) include("${CMAKE_CURRENT_SOURCE_DIR}/modules/code-coverage.cmake") add_code_coverage_all_targets(EXCLUDE odbc-test) -set(CMAKE_CXX_STANDARD 98) +set(CMAKE_CXX_STANDARD 11) set(CMAKE_PROJECT_VERSION ${PROJECT_VERSION}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") From 827f2bcf15dea7ad4ed8cd01e527412a4302444b Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 14:28:56 -0800 Subject: [PATCH 034/165] [AD-522] change fetchSize to defaultFetchSize on configuration window for consistency with JDBC driver --- .../odbc/system/ui/dsn_configuration_window.h | 12 +++++----- .../system/ui/dsn_configuration_window.cpp | 22 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index e17d0270c..bc1750d37 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -72,8 +72,8 @@ namespace ignite REPLICA_SET_EDIT, REPLICA_SET_LABEL, RETRY_READS_CHECK_BOX, - FETCH_SIZE_EDIT, - FETCH_SIZE_LABEL, + DEFAULT_FETCH_SIZE_EDIT, + DEFAULT_FETCH_SIZE_LABEL, PROTOCOL_VERSION_LABEL, PROTOCOL_VERSION_COMBO_BOX, NESTED_TX_MODE_LABEL, @@ -326,11 +326,11 @@ namespace ignite /** Retry reads checkBox. */ std::auto_ptr retryReadsCheckBox; - /** Fetch size edit. */ - std::auto_ptr fetchSizeEdit; + /** Default fetch size edit. */ + std::auto_ptr defaultFetchSizeEdit; - /** Fetch size label. */ - std::auto_ptr fetchSizeLabel; + /** Default fetch size label. */ + std::auto_ptr defaultFetchSizeLabel; /** Protocol version edit field. */ std::auto_ptr protocolVersionLabel; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 4c156b873..0ed0b9342 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -68,8 +68,8 @@ namespace ignite replicaSetLabel(), replicaSetEdit(), retryReadsCheckBox(), - fetchSizeLabel(), - fetchSizeEdit(), + defaultFetchSizeLabel(), + defaultFetchSizeEdit(), protocolVersionLabel(), protocolVersionComboBox(), userLabel(), @@ -274,7 +274,7 @@ namespace ignite sshKnownHostsFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSH known hosts:", ChildId::SSH_KNOWN_HOSTS_FILE_LABEL); sshKnownHostsFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, - ChildId::SSH_KNOWN_HOST_FILE_EDIT); + ChildId::SSH_KNOWN_HOSTS_FILE_EDIT); rowPos += INTERVAL + ROW_HEIGHT; @@ -381,13 +381,13 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - tmp = common::LexicalCast(config.GetFetchSize()); + tmp = common::LexicalCast(config.GetDefaultFetchSize()); val = tmp.c_str(); - fetchSizeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, - ROW_HEIGHT, "Fetch size:", ChildId::FETCH_SIZE_LABEL); + defaultFetchSizeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, + ROW_HEIGHT, "Fetch size:", ChildId::DEFAULT_FETCH_SIZE_LABEL); - fetchSizeEdit = CreateEdit(editPosX, rowPos, editSizeX, - ROW_HEIGHT, val, ChildId::FETCH_SIZE_EDIT, ES_NUMBER); + defaultFetchSizeEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, ChildId::DEFAULT_FETCH_SIZE_EDIT, ES_NUMBER); rowPos += INTERVAL + ROW_HEIGHT; @@ -587,13 +587,13 @@ namespace ignite std::string fetchSizeStr; - fetchSizeEdit->GetText(fetchSizeStr); + defaultFetchSizeEdit->GetText(fetchSizeStr); int32_t fetchSize = common::LexicalCast< int32_t >(fetchSizeStr); if (fetchSize <= 0) - fetchSize = config.GetFetchSize(); + fetchSize = config.GetDefaultFetchSize(); LOG_MSG("Retrieving arguments:"); LOG_MSG("App name: " << appNameStr); @@ -608,7 +608,7 @@ namespace ignite cfg.SetReadPreference(readPreferenceStr); cfg.SetReplicaSet(replicaSetStr); cfg.SetRetryReads(retryReads); - cfg.SetFetchSize(fetchSize); + cfg.SetDefaultFetchSize(fetchSize); } } From 5c015497b4f7836f03f8daf870b4808be9bb1edb Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Thu, 20 Jan 2022 14:56:36 -0800 Subject: [PATCH 035/165] [AD-517] * Changed checks.yml so that it doesn't fail on code review errors. --- .github/workflows/checks.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index ffa776c01..d3fec3b10 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -10,6 +10,5 @@ jobs: - uses: actions/checkout@v2 - uses: ZedThree/clang-tidy-review@v0.7.0 id: review - - if: steps.review.outputs.total_comments > 0 - run: exit 1 + continue-on-error: true From aa7731a67f123c8942b89cba8334efe15776f6c8 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 15:06:55 -0800 Subject: [PATCH 036/165] Revert "[AD-522] bugfix - change DefaultFetchSize to fetchSize in all related files to be consistent with configuration.h"" This reverts commit 124b7256d8f96fb31363aa2efb0423b115b11b0a. --- .../ignite/odbc/config/connection_string_parser.h | 2 +- src/odbc/src/config/connection_string_parser.cpp | 6 +++--- src/odbc/src/dsn_config.cpp | 10 +++++----- src/odbc/src/query/batch_query.cpp | 2 +- src/odbc/src/query/data_query.cpp | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index 27e4f48d2..ba557d6c3 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -120,7 +120,7 @@ namespace ignite static const std::string protocolVersion; /** Connection attribute keyword for fetch results page size attribute. */ - static const std::string defaultFetchSize; + static const std::string fetchSize; /** Connection attribute keyword for sslMode attribute. */ static const std::string sslMode; diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index 308bb225b..a05e2a530 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -57,7 +57,7 @@ namespace ignite const std::string ConnectionStringParser::Key::scanLimit = "scan_limit"; const std::string ConnectionStringParser::Key::schemaName = "schema_name"; const std::string ConnectionStringParser::Key::refreshSchema = "refresh_schema"; - const std::string ConnectionStringParser::Key::defaultFetchSize = "default_fetch_size"; + const std::string ConnectionStringParser::Key::fetchSize = "fetch_size"; const std::string ConnectionStringParser::Key::uid = "uid"; const std::string ConnectionStringParser::Key::pwd = "pwd"; @@ -399,7 +399,7 @@ namespace ignite cfg.SetTls(res == BoolParseResult::AI_TRUE); } - else if (lKey == Key::defaultFetchSize) + else if (lKey == Key::fetchSize) { if (!common::AllDigits(value)) { @@ -443,7 +443,7 @@ namespace ignite return; } - cfg.SetDefaultFetchSize(static_cast(numValue)); + cfg.SetFetchSize(static_cast(numValue)); } else if (lKey == Key::tlsCaFile) { diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 6526a38bd..9b02548ed 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -219,7 +219,7 @@ namespace ignite if (scanLimit.IsSet() && !config.IsScanLimitSet() && scanLimit.GetValue() > 0) - config.SetDefaultFetchSize(scanLimit.GetValue()); + config.SetFetchSize(scanLimit.GetValue()); SettableValue schemaName = ReadDsnString(dsn, ConnectionStringParser::Key::schemaName); @@ -231,11 +231,11 @@ namespace ignite if (refreshSchema.IsSet() && !config.IsSchemaRefreshSet()) config.SetSchemaRefresh(refreshSchema.GetValue()); - SettableValue defaultFetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::defaultFetchSize); + SettableValue fetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::fetchSize); - if (defaultFetchSize.IsSet() && !config.IsDefaultFetchSizeSet() - && defaultFetchSize.GetValue() > 0) - config.SetDefaultFetchSize(defaultFetchSize.GetValue()); + if (fetchSize.IsSet() && !config.IsFetchSizeSet() + && fetchSize.GetValue() > 0) + config.SetFetchSize(fetchSize.GetValue()); } } } diff --git a/src/odbc/src/query/batch_query.cpp b/src/odbc/src/query/batch_query.cpp index 7390b4f59..6a82d690e 100644 --- a/src/odbc/src/query/batch_query.cpp +++ b/src/odbc/src/query/batch_query.cpp @@ -52,7 +52,7 @@ namespace ignite if (executed) Close(); - int32_t maxPageSize = connection.GetConfiguration().GetDefaultFetchSize(); + int32_t maxPageSize = connection.GetConfiguration().GetFetchSize(); int32_t rowNum = params.GetParamSetSize(); SqlResult::Type res; diff --git a/src/odbc/src/query/data_query.cpp b/src/odbc/src/query/data_query.cpp index d5c4d6a6d..28a9ab72f 100644 --- a/src/odbc/src/query/data_query.cpp +++ b/src/odbc/src/query/data_query.cpp @@ -193,7 +193,7 @@ namespace ignite if (affected >= 0) return affected; - return connection.GetConfiguration().GetDefaultFetchSize(); + return connection.GetConfiguration().GetFetchSize(); } SqlResult::Type DataQuery::NextResultSet() @@ -320,7 +320,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); + QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetFetchSize()); QueryFetchResponse rsp(*resultPage); try @@ -361,7 +361,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); + QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetFetchSize()); QueryMoreResultsResponse rsp(*resultPage); try From 20a84063dcf61ea2301ea8b6b145289fa71f42eb Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 15:08:26 -0800 Subject: [PATCH 037/165] [AD-522] make TLS allow invalid hostnames checkbox enabled only when tls Check box is checked --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 0ed0b9342..03131910c 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -279,7 +279,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; sshSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "Internal SSH Tunnel settings", + "Internal SSH tunnel settings", ChildId::SSH_SETTINGS_GROUP_BOX); return rowPos - posY; @@ -321,6 +321,7 @@ namespace ignite sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "TLS/SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); + tlsCheckBox->SetEnabled(tlsCheckBox->IsChecked()); tlsCaFileEdit->SetEnabled(tlsCheckBox->IsChecked()); return rowPos - posY; @@ -434,6 +435,8 @@ namespace ignite case ChildId::TLS_CHECK_BOX: { tlsCheckBox->SetChecked(!tlsCheckBox->IsChecked()); + tlsAllowInvalidHostnamesCheckBox + ->SetEnabled(tlsCheckBox->IsChecked()); tlsCaFileEdit->SetEnabled(tlsCheckBox->IsChecked()); break; From 0b1a768a349dc0c737a854cbaecff0629c52371d Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 20 Jan 2022 15:17:41 -0800 Subject: [PATCH 038/165] Revert "Revert "[AD-522] bugfix - change DefaultFetchSize to fetchSize in all related files to be consistent with configuration.h""" This reverts commit aa7731a67f123c8942b89cba8334efe15776f6c8. --- .../ignite/odbc/config/connection_string_parser.h | 2 +- src/odbc/src/config/connection_string_parser.cpp | 6 +++--- src/odbc/src/dsn_config.cpp | 10 +++++----- src/odbc/src/query/batch_query.cpp | 2 +- src/odbc/src/query/data_query.cpp | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index ba557d6c3..27e4f48d2 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -120,7 +120,7 @@ namespace ignite static const std::string protocolVersion; /** Connection attribute keyword for fetch results page size attribute. */ - static const std::string fetchSize; + static const std::string defaultFetchSize; /** Connection attribute keyword for sslMode attribute. */ static const std::string sslMode; diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index a05e2a530..308bb225b 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -57,7 +57,7 @@ namespace ignite const std::string ConnectionStringParser::Key::scanLimit = "scan_limit"; const std::string ConnectionStringParser::Key::schemaName = "schema_name"; const std::string ConnectionStringParser::Key::refreshSchema = "refresh_schema"; - const std::string ConnectionStringParser::Key::fetchSize = "fetch_size"; + const std::string ConnectionStringParser::Key::defaultFetchSize = "default_fetch_size"; const std::string ConnectionStringParser::Key::uid = "uid"; const std::string ConnectionStringParser::Key::pwd = "pwd"; @@ -399,7 +399,7 @@ namespace ignite cfg.SetTls(res == BoolParseResult::AI_TRUE); } - else if (lKey == Key::fetchSize) + else if (lKey == Key::defaultFetchSize) { if (!common::AllDigits(value)) { @@ -443,7 +443,7 @@ namespace ignite return; } - cfg.SetFetchSize(static_cast(numValue)); + cfg.SetDefaultFetchSize(static_cast(numValue)); } else if (lKey == Key::tlsCaFile) { diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 9b02548ed..6526a38bd 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -219,7 +219,7 @@ namespace ignite if (scanLimit.IsSet() && !config.IsScanLimitSet() && scanLimit.GetValue() > 0) - config.SetFetchSize(scanLimit.GetValue()); + config.SetDefaultFetchSize(scanLimit.GetValue()); SettableValue schemaName = ReadDsnString(dsn, ConnectionStringParser::Key::schemaName); @@ -231,11 +231,11 @@ namespace ignite if (refreshSchema.IsSet() && !config.IsSchemaRefreshSet()) config.SetSchemaRefresh(refreshSchema.GetValue()); - SettableValue fetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::fetchSize); + SettableValue defaultFetchSize = ReadDsnInt(dsn, ConnectionStringParser::Key::defaultFetchSize); - if (fetchSize.IsSet() && !config.IsFetchSizeSet() - && fetchSize.GetValue() > 0) - config.SetFetchSize(fetchSize.GetValue()); + if (defaultFetchSize.IsSet() && !config.IsDefaultFetchSizeSet() + && defaultFetchSize.GetValue() > 0) + config.SetDefaultFetchSize(defaultFetchSize.GetValue()); } } } diff --git a/src/odbc/src/query/batch_query.cpp b/src/odbc/src/query/batch_query.cpp index 6a82d690e..7390b4f59 100644 --- a/src/odbc/src/query/batch_query.cpp +++ b/src/odbc/src/query/batch_query.cpp @@ -52,7 +52,7 @@ namespace ignite if (executed) Close(); - int32_t maxPageSize = connection.GetConfiguration().GetFetchSize(); + int32_t maxPageSize = connection.GetConfiguration().GetDefaultFetchSize(); int32_t rowNum = params.GetParamSetSize(); SqlResult::Type res; diff --git a/src/odbc/src/query/data_query.cpp b/src/odbc/src/query/data_query.cpp index 28a9ab72f..d5c4d6a6d 100644 --- a/src/odbc/src/query/data_query.cpp +++ b/src/odbc/src/query/data_query.cpp @@ -193,7 +193,7 @@ namespace ignite if (affected >= 0) return affected; - return connection.GetConfiguration().GetFetchSize(); + return connection.GetConfiguration().GetDefaultFetchSize(); } SqlResult::Type DataQuery::NextResultSet() @@ -320,7 +320,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetFetchSize()); + QueryFetchRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); QueryFetchResponse rsp(*resultPage); try @@ -361,7 +361,7 @@ namespace ignite { std::auto_ptr resultPage(new ResultPage()); - QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetFetchSize()); + QueryMoreResultsRequest req(cursor->GetQueryId(), connection.GetConfiguration().GetDefaultFetchSize()); QueryMoreResultsResponse rsp(*resultPage); try From c34c5a2289f97b8e6ba05dd40cb59da963604615 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Thu, 20 Jan 2022 17:38:35 -0800 Subject: [PATCH 039/165] Improvements from review --- .../odbc/config/connection_string_parser.h | 10 ++-------- src/odbc/src/config/configuration.cpp | 4 ++-- .../src/config/connection_string_parser.cpp | 5 ++--- src/odbc/src/dsn_config.cpp | 6 +++--- src/odbc/src/message.cpp | 20 ------------------- 5 files changed, 9 insertions(+), 36 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index f88411c7e..6693eb706 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -47,11 +47,8 @@ namespace ignite /** Connection attribute keyword for schema attribute. */ static const std::string database; - /** Connection attribute keyword for address attribute. */ - static const std::string address; - - /** Connection attribute keyword for server attribute. */ - static const std::string server; + /** Connection attribute keyword for hostname attribute. */ + static const std::string hostname; /** Connection attribute keyword for port attribute. */ static const std::string port; @@ -116,9 +113,6 @@ namespace ignite /** Connection attribute keyword for password attribute. */ static const std::string refreshSchema; - /** Connection attribute keyword for protocol version attribute. */ - static const std::string protocolVersion; - /** Connection attribute keyword for defaultFetchSize attribute. */ static const std::string defaultFetchSize; diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index c43d8262e..d6a6e2cb9 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -32,7 +32,7 @@ namespace ignite { const std::string Configuration::DefaultValue::dsn = "DocumentDB DSN"; - const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB Driver"; + const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB ODBC Driver"; const std::string Configuration::DefaultValue::database = ""; const std::string Configuration::DefaultValue::hostname = ""; const uint16_t Configuration::DefaultValue::port = 27017; @@ -520,7 +520,7 @@ namespace ignite AddToMap(res, ConnectionStringParser::Key::dsn, dsn); AddToMap(res, ConnectionStringParser::Key::driver, driver); AddToMap(res, ConnectionStringParser::Key::database, database); - AddToMap(res, ConnectionStringParser::Key::server, hostname); + AddToMap(res, ConnectionStringParser::Key::hostname, hostname); AddToMap(res, ConnectionStringParser::Key::port, port); AddToMap(res, ConnectionStringParser::Key::user, user); AddToMap(res, ConnectionStringParser::Key::password, password); diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index 96ba6b58d..6d6cff010 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -34,8 +34,7 @@ namespace ignite const std::string ConnectionStringParser::Key::dsn = "dsn"; const std::string ConnectionStringParser::Key::driver = "driver"; const std::string ConnectionStringParser::Key::database = "database"; - const std::string ConnectionStringParser::Key::address = "address"; - const std::string ConnectionStringParser::Key::server = "hostname"; + const std::string ConnectionStringParser::Key::hostname = "hostname"; const std::string ConnectionStringParser::Key::port = "port"; const std::string ConnectionStringParser::Key::user = "user"; const std::string ConnectionStringParser::Key::password = "password"; @@ -151,7 +150,7 @@ namespace ignite { cfg.SetDatabase(value); } - else if (lKey == Key::server) + else if (lKey == Key::hostname) { EndPoint endpoint; diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index c9fd4a0fb..9b2b7ac91 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -104,10 +104,10 @@ namespace ignite void ReadDsnConfiguration(const char* dsn, Configuration& config, diagnostic::DiagnosticRecordStorage* diag) { - SettableValue server = ReadDsnString(dsn, ConnectionStringParser::Key::server); + SettableValue hostname = ReadDsnString(dsn, ConnectionStringParser::Key::hostname); - if (server.IsSet() && !config.IsHostnameSet()) - config.SetHostname(server.GetValue()); + if (hostname.IsSet() && !config.IsHostnameSet()) + config.SetHostname(hostname.GetValue()); SettableValue port = ReadDsnInt(dsn, ConnectionStringParser::Key::port); diff --git a/src/odbc/src/message.cpp b/src/odbc/src/message.cpp index 80b809205..138c91485 100644 --- a/src/odbc/src/message.cpp +++ b/src/odbc/src/message.cpp @@ -68,26 +68,6 @@ namespace ignite writer.WriteInt16(version.GetMaintenance()); writer.WriteInt8(ClientType::ODBC); - - /*writer.WriteBool(config.IsDistributedJoins()); - writer.WriteBool(config.IsEnforceJoinOrder()); - writer.WriteBool(config.IsReplicatedOnly()); - writer.WriteBool(config.IsCollocated()); - - if (version >= ProtocolVersion::VERSION_2_1_5) - writer.WriteBool(config.IsLazy()); - - if (version >= ProtocolVersion::VERSION_2_3_0) - writer.WriteBool(config.IsSkipReducerOnUpdate()); - - if (version >= ProtocolVersion::VERSION_2_5_0) - { - utility::WriteString(writer, config.GetUser()); - utility::WriteString(writer, config.GetPassword()); - } - - if (version >= ProtocolVersion::VERSION_2_7_0) - writer.WriteInt8(config.GetNestedTxMode());*/ } QueryExecuteRequest::QueryExecuteRequest(const std::string& schema, const std::string& sql, From 1a66e9b41364ad48683864806bfd8c40ae8680ab Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Thu, 20 Jan 2022 17:49:29 -0800 Subject: [PATCH 040/165] Updated comments --- .../odbc/config/connection_string_parser.h | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index 6693eb706..16b02d484 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -44,7 +44,7 @@ namespace ignite /** Connection attribute keyword for Driver attribute. */ static const std::string driver; - /** Connection attribute keyword for schema attribute. */ + /** Connection attribute keyword for database attribute. */ static const std::string database; /** Connection attribute keyword for hostname attribute. */ @@ -59,58 +59,58 @@ namespace ignite /** Connection attribute keyword for password attribute. */ static const std::string password; - /** Connection attribute keyword for username attribute. */ + /** Connection attribute keyword for appName attribute. */ static const std::string appName; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for loginTimeoutSec attribute. */ static const std::string loginTimeoutSec; - /** Connection attribute keyword for username attribute. */ + /** Connection attribute keyword for readPreference attribute. */ static const std::string readPreference; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for replicaSet attribute. */ static const std::string replicaSet; - /** Connection attribute keyword for username attribute. */ + /** Connection attribute keyword for retryReads attribute. */ static const std::string retryReads; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for tls attribute. */ static const std::string tls; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for tlsAllowInvalidHostnames attribute. */ static const std::string tlsAllowInvalidHostnames; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for tlsCaFile attribute. */ static const std::string tlsCaFile; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for sshUser attribute. */ static const std::string sshUser; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for sshHost attribute. */ static const std::string sshHost; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for sshPrivateKeyFile attribute. */ static const std::string sshPrivateKeyFile; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for sshPrivateKeyPassphrase attribute. */ static const std::string sshPrivateKeyPassphrase; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for sshStrictHostKeyChecking attribute. */ static const std::string sshStrictHostKeyChecking; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for sshKnownHostsFile attribute. */ static const std::string sshKnownHostsFile; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for scanMethod attribute. */ static const std::string scanMethod; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for scanLimit attribute. */ static const std::string scanLimit; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for schemaName attribute. */ static const std::string schemaName; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for refreshSchema attribute. */ static const std::string refreshSchema; /** Connection attribute keyword for defaultFetchSize attribute. */ From 961d8cbee303fd2b25ed64bc5589f9fb4d8ac23e Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 21 Jan 2022 10:36:14 -0800 Subject: [PATCH 041/165] [AD-522] save SSH values for re-read, make settings window into 2 columns Make ssl and additional settings groups to be on the right side of the column on the configuration window. This is subject to change later. I created the function void DsnConfigurationWindow::RetrieveSshParameters(config::Configuration& cfg) const to save SSH values. The width value in the DsnConfigurationWindow constructor is doubled from 360 to 720 and added the margin value. The margins currently look imbalanced on the settings box, and will be fixed in later commits. Make Ok button and Cancel buttons aligned with the right column bugfix - allow the SSH strict host checking checkbox to be checked on and off by adding the case ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX definition. --- .../odbc/system/ui/dsn_configuration_window.h | 8 + .../system/ui/dsn_configuration_window.cpp | 252 +++++++++++++++++- 2 files changed, 246 insertions(+), 14 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index bc1750d37..448ba71e2 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -161,6 +161,14 @@ namespace ignite */ void RetrieveAuthParameters(config::Configuration& cfg) const; + /** + * Retrieves current values from the SSH tunnel UI group and + * stores them to the specified configuration. + * + * @param cfg Configuration. + */ + void RetrieveSshParameters(config::Configuration& cfg) const; + /** * Retrieves current values from the SSL UI group and * stores them to the specified configuration. diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 03131910c..835982444 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -35,8 +35,11 @@ namespace ignite { // -AL- the constructor. No-op means no operation I think? DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, config::Configuration& config): CustomWindow(parent, "IgniteConfigureDsn", "Configure Amazon DocumentDB DSN Latest"), - width(360), - height(600), + //width(360), // original width:360. + height(600), // original height:600 + width(730), // double the original width + //width(360), + //height(800), connectionSettingsGroupBox(), sslSettingsGroupBox(), // has a create... function defined tlsCheckBox(), @@ -117,23 +120,33 @@ namespace ignite // the function that actually creates the UI -AL- void DsnConfigurationWindow::OnCreate() { - int groupPosY = MARGIN; - int groupSizeY = width - 2 * MARGIN; - - groupPosY += INTERVAL + CreateConnectionSettingsGroup(MARGIN, groupPosY, groupSizeY); - groupPosY += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosY, groupSizeY); - groupPosY += INTERVAL + CreateSshSettingsGroup(MARGIN, groupPosY, groupSizeY); - groupPosY += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosY, groupSizeY); - groupPosY += INTERVAL + CreateAdditionalSettingsGroup(MARGIN, groupPosY, groupSizeY); + int groupPosYLeft = MARGIN; + //int groupSizeY = width - 2 * MARGIN; // original + int groupSizeY = (width - 2 * MARGIN) / 2; + int posXRight = MARGIN + (width - MARGIN) / 2; + int groupPosYRight = MARGIN; + + groupPosYLeft += INTERVAL + CreateConnectionSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); + groupPosYLeft += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); + groupPosYLeft += INTERVAL + CreateSshSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); + groupPosYRight += INTERVAL + CreateSslSettingsGroup(posXRight, groupPosYRight, groupSizeY); + groupPosYRight += INTERVAL + CreateAdditionalSettingsGroup(posXRight, groupPosYRight, groupSizeY); + //groupPosY += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosY, groupSizeY); + //groupPosY += INTERVAL + CreateAdditionalSettingsGroup(MARGIN, groupPosY, groupSizeY); // test: if above code is commented out, additional settings shouldn't appear in config window. Result: Yes test success. // what happens here is the height of each subgroup is calculated and appended to the y position of the buttons int cancelPosX = width - MARGIN - BUTTON_WIDTH; int okPosX = cancelPosX - INTERVAL - BUTTON_WIDTH; - okButton = CreateButton(okPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, "Ok", ChildId::OK_BUTTON); - cancelButton = CreateButton(cancelPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, + okButton = CreateButton(okPosX, groupPosYRight, BUTTON_WIDTH, BUTTON_HEIGHT, "Ok", ChildId::OK_BUTTON); + cancelButton = CreateButton(cancelPosX, groupPosYRight, BUTTON_WIDTH, BUTTON_HEIGHT, "Cancel", ChildId::CANCEL_BUTTON); + + // original code by Ignite + //okButton = CreateButton(okPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, "Ok", ChildId::OK_BUTTON); + //cancelButton = CreateButton(cancelPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, + // "Cancel", ChildId::CANCEL_BUTTON); } int DsnConfigurationWindow::CreateConnectionSettingsGroup(int posX, int posY, int sizeX) @@ -285,6 +298,8 @@ namespace ignite return rowPos - posY; } + // old SSL settings group code for 1 column config window + /* int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) { // TODO: rename function name from Ssl to TLS after UI works @@ -326,7 +341,52 @@ namespace ignite return rowPos - posY; } + */ + + int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) + { // TODO: rename function name from Ssl to TLS after UI works + + enum { LABEL_WIDTH = 120 }; + + int labelPosX = posX + INTERVAL; + + int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + int rowPos = posY + 2 * INTERVAL; + + int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; + + tlsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, + "TLS", ChildId::TLS_CHECK_BOX, config.IsTls()); + + tlsAllowInvalidHostnamesCheckBox = CreateCheckBox( + labelPosX + checkBoxSize + INTERVAL, rowPos, + checkBoxSize, ROW_HEIGHT, "TLS Allow Invalid Hostnames", + ChildId::TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, + config.IsTlsAllowInvalidHostnames()); + + rowPos += INTERVAL + ROW_HEIGHT; + + const char* val = config.GetTlsCaFile().c_str(); + tlsCaFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "TLS Certificate Authority:", ChildId::TLS_CA_FILE_LABEL); + tlsCaFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, + ChildId::TLS_CA_FILE_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "TLS/SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); + + tlsAllowInvalidHostnamesCheckBox->SetEnabled(tlsCheckBox->IsChecked()); + tlsCaFileEdit->SetEnabled(tlsCheckBox->IsChecked()); + + return rowPos - posY; + } + + // old additional settings group code for 1 column window + /* int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) { enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also change it to the same @@ -359,6 +419,25 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; + // useful draft code for changing read preference into a mode (check JDBC page for available options) + // const char* val = sslModeStr.c_str(); + + // sslModeLabel = CreateLabel(labelPosX, rowPos, + // LABEL_WIDTH, ROW_HEIGHT, + // "SSL Mode:", ChildId::SSL_MODE_LABEL); + // sslModeComboBox = CreateComboBox(editPosX, rowPos, + // editSizeX, ROW_HEIGHT, + // "", ChildId::SSL_MODE_COMBO_BOX); + + // sslModeComboBox->AddString("disable"); + // sslModeComboBox->AddString("require"); + + // sslModeComboBox->SetSelection(sslMode); // set default + // value to require -AL- + + // rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight + // I believe + val = config.GetReadPreference().c_str(); readPreferenceLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, @@ -397,7 +476,117 @@ namespace ignite return rowPos - posY; } - + */ + + int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) { + enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also + // change it to the same + + int labelPosX = posX + INTERVAL; + + int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + + int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; + + int rowPos = posY + 2 * INTERVAL; + + const char* val = config.GetApplicationName().c_str(); + + appNameLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Application Name:", ChildId::APP_NAME_LABEL); + appNameEdit = + CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, + ChildId::APP_NAME_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + std::string tmp = common::LexicalCast< std::string >( + config.GetLoginTimeoutSeconds()); + val = tmp.c_str(); + loginTimeoutSecLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Login Timeout (s):", ChildId::LOGIN_TIMEOUT_SEC_LABEL); + + loginTimeoutSecEdit = CreateEdit( + editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::LOGIN_TIMEOUT_SEC_EDIT, ES_NUMBER); + + rowPos += INTERVAL + ROW_HEIGHT; + + // useful draft code for changing read preference into a + // mode (check JDBC page for available options) const char* + // val = sslModeStr.c_str(); + + // sslModeLabel = CreateLabel(labelPosX, rowPos, + // LABEL_WIDTH, ROW_HEIGHT, + // "SSL Mode:", ChildId::SSL_MODE_LABEL); + // sslModeComboBox = CreateComboBox(editPosX, rowPos, + // editSizeX, ROW_HEIGHT, + // "", ChildId::SSL_MODE_COMBO_BOX); + + // sslModeComboBox->AddString("disable"); + // sslModeComboBox->AddString("require"); + + // sslModeComboBox->SetSelection(sslMode); // set default + // value to require -AL- + + // rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight + // I believe + + val = config.GetReadPreference().c_str(); + + readPreferenceLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Read preference:", ChildId::READ_PREFERENCE_LABEL); + readPreferenceEdit = CreateEdit( + editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::READ_PREFERENCE_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetReplicaSet().c_str(); + + replicaSetLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Replica Set:", ChildId::REPLICA_SET_LABEL); + replicaSetEdit = + CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, + ChildId::REPLICA_SET_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + retryReadsCheckBox = CreateCheckBox( + labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, + "Retry Reads", ChildId::RETRY_READS_CHECK_BOX, + config.IsRetryReads()); + + rowPos += INTERVAL + ROW_HEIGHT; + + tmp = common::LexicalCast< std::string >( + config.GetDefaultFetchSize()); + val = tmp.c_str(); + defaultFetchSizeLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Fetch size:", ChildId::DEFAULT_FETCH_SIZE_LABEL); + + defaultFetchSizeEdit = CreateEdit( + editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::DEFAULT_FETCH_SIZE_EDIT, ES_NUMBER); + + rowPos += INTERVAL + ROW_HEIGHT; + + additionalSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, + rowPos - posY, "Additional settings", + ChildId::ADDITIONAL_SETTINGS_GROUP_BOX); + + return rowPos - posY; + } + + bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) @@ -432,6 +621,13 @@ namespace ignite break; } + case ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX: + { + sshStrictHostKeyCheckingCheckBox + ->SetChecked(!sshStrictHostKeyCheckingCheckBox->IsChecked()); + break; + } + case ChildId::TLS_CHECK_BOX: { tlsCheckBox->SetChecked(!tlsCheckBox->IsChecked()); @@ -546,6 +742,34 @@ namespace ignite cfg.SetPassword(password); } + void DsnConfigurationWindow::RetrieveSshParameters(config::Configuration& cfg) const + { + std::string sshUserStr; + std::string sshHostStr; + std::string sshPrivateKeyFileStr; + std::string sshPrivateKeyPassphraseStr; + std::string sshKnownHostsFileStr; + + sshUserEdit->GetText(sshUserStr); + sshHostEdit->GetText(sshHostStr); + //sshPrivateKeyFileEdit->GetText(sshPrivateKeyFileStr); + //sshPrivateKeyPassphraseEdit->GetText(sshPrivateKeyPassphraseStr); + sshKnownHostsFileEdit->GetText(sshKnownHostsFileStr); + + bool sshStrictHostKeyChecking = sshStrictHostKeyCheckingCheckBox->IsChecked(); + + LOG_MSG("SSH user: " << sshUserStr); + LOG_MSG("SSH host: " << sshHostStr); + LOG_MSG("SSH known hosts file: " << sshKnownHostsFileStr); + LOG_MSG("SSH strict host key checking: " << (sshStrictHostKeyChecking ? "true" : "false")); + + cfg.SetSshUser(sshUserStr); + cfg.SetSshHost(sshHostStr); + cfg.SetSshKnownHostsFile(sshKnownHostsFileStr); + cfg.SetSshStrictHostKeyChecking(sshStrictHostKeyChecking); + + } + void DsnConfigurationWindow::RetrieveSslParameters(config::Configuration& cfg) const { @@ -557,7 +781,7 @@ namespace ignite LOG_MSG("TLS/SSL Encryption: " << (tls ? "true" : "false")); LOG_MSG("tls Allow Invalid Hostnames: " << (tlsAllowInvalidHostnames ? "true" : "false")); - LOG_MSG("TLS CA: " << tlsCaStr); + LOG_MSG("TLS CA (Certificate Authority): " << tlsCaStr); cfg.SetTls(tls); cfg.SetTlsAllowInvalidHostnames(tlsAllowInvalidHostnames); From adaf439164d3fcfde1287442d079b339dd6c6283 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Fri, 21 Jan 2022 11:29:59 -0800 Subject: [PATCH 042/165] Removed includes no longer being used in configuration.h --- src/odbc/include/ignite/odbc/config/configuration.h | 5 +---- src/odbc/include/ignite/odbc/connection.h | 1 + .../include/ignite/odbc/system/ui/dsn_configuration_window.h | 4 ++++ src/odbc/src/config/connection_string_parser.cpp | 4 ++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index a7b87ad5c..e8381eb31 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -22,11 +22,8 @@ #include #include -#include "ignite/odbc/protocol_version.h" #include "ignite/odbc/config/settable_value.h" -#include "ignite/odbc/ssl_mode.h" -#include "ignite/odbc/end_point.h" -#include "ignite/odbc/nested_tx_mode.h" +#include "ignite/odbc/diagnostic/diagnosable.h" #include "ignite/odbc/read_preference.h" #include "ignite/odbc/scan_method.h" diff --git a/src/odbc/include/ignite/odbc/connection.h b/src/odbc/include/ignite/odbc/connection.h index b670ee074..3fefc8e33 100644 --- a/src/odbc/include/ignite/odbc/connection.h +++ b/src/odbc/include/ignite/odbc/connection.h @@ -30,6 +30,7 @@ #include "ignite/odbc/diagnostic/diagnosable_adapter.h" #include "ignite/odbc/streaming/streaming_context.h" #include "ignite/odbc/odbc_error.h" +#include "ignite/odbc/end_point.h" namespace ignite { diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 77974ade3..26acd47ac 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -20,6 +20,10 @@ #include "ignite/odbc/config/configuration.h" #include "ignite/odbc/system/ui/custom_window.h" +// TODO: Removed these from configuration.h since no longer used. Moved here since they are still referenced. Remove when no longer needed. +#include "ignite/odbc/nested_tx_mode.h" +#include "ignite/odbc/protocol_version.h" +#include "ignite/odbc/ssl_mode.h" namespace ignite { diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index 6d6cff010..b6e7908fc 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -20,10 +20,10 @@ #include "ignite/common/utils.h" #include "ignite/odbc/utility.h" -#include "ignite/odbc/ssl_mode.h" +//#include "ignite/odbc/ssl_mode.h" #include "ignite/odbc/config/connection_string_parser.h" #include "ignite/odbc/config/config_tools.h" -#include "ignite/odbc/nested_tx_mode.h" +//#include "ignite/odbc/nested_tx_mode.h" namespace ignite { From 44f5c70159bc22ad6b98a4d5ba2a21f49faae3eb Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Fri, 21 Jan 2022 13:54:05 -0800 Subject: [PATCH 043/165] Some formatting improvements --- src/odbc/include/ignite/odbc/config/configuration.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index e8381eb31..ee52f697c 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -647,7 +647,7 @@ namespace ignite /** * Get refresh schema flag. * - * @return Password. + * @return @true if refreshing schema is enabled. */ bool IsRefreshSchema() const; From b9b2d031fe39ebf1421200c2cb2d38518850c4ab Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 21 Jan 2022 14:09:33 -0800 Subject: [PATCH 044/165] [Ad-522] add sshEnable variable in DSN config - added sshEnable variable definition and getter/setter for sshEnable. - added code for parsing sshEnable in the connection string parser --- .../ignite/odbc/config/configuration.h | 27 +++++++++++++++++++ .../odbc/config/connection_string_parser.h | 3 +++ src/odbc/src/config/configuration.cpp | 15 ++++++++++- .../src/config/connection_string_parser.cpp | 20 ++++++++++++++ src/odbc/src/dsn_config.cpp | 5 ++++ 5 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index c5a021c2d..254140b09 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -97,6 +97,9 @@ namespace ignite /** Default value for tlsCaFile attribute. */ static const std::string tlsCaFile; + /** Default value for sshEnable attribute. */ + static const bool sshEnable; + /** Default value for sshUser attribute. */ static const std::string sshUser; @@ -467,6 +470,27 @@ namespace ignite */ bool IsTlsCaFileSet() const; + /** + * Get ssh enable. + * + * @return sshEnable. + */ + bool GetSshEnable() const; + + /** + * Set ssh enable. + * + * @param bool ssh enable. + */ + void SetSshEnable(bool sshEnable); + + /** + * Check if the ssh enable value set. + * + * @return @true if the ssh enable value set. + */ + bool IsSshEnableSet() const; + /** * Get password. * @@ -785,6 +809,9 @@ namespace ignite /** SSL/TLS certificate authority file path. */ SettableValue tlsCaFile; + /** The SSH enable option for the internal SSH tunnel. */ + SettableValue sshEnable; + /** The SSH host username for the internal SSH tunnel. */ SettableValue sshUser; diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index 27e4f48d2..3e8169057 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -86,6 +86,9 @@ namespace ignite /** Connection attribute keyword for password attribute. */ static const std::string tlsCaFile; + /** Connection attribute keyword for ssh enable attribute. */ + static const std::string sshEnable; + /** Connection attribute keyword for password attribute. */ static const std::string sshUser; diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 50aedf5c7..67058770d 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -52,7 +52,7 @@ namespace ignite const bool Configuration::DefaultValue::refreshSchema = false; // Internal SSH Tunnel options // need to add to UI - // const bool Configuration::DefaultValue::sshEnable = false; + const bool Configuration::DefaultValue::sshEnable = false; const std::string Configuration::DefaultValue::sshUser = ""; const std::string Configuration::DefaultValue::sshHost = ""; const std::string Configuration::DefaultValue::sshPrivateKeyFile = ""; @@ -87,6 +87,7 @@ namespace ignite tls(DefaultValue::tls), tlsAllowInvalidHostnames(DefaultValue::tlsAllowInvalidHostnames), tlsCaFile(DefaultValue::tlsCaFile), + sshEnable(DefaultValue::sshEnable), sshUser(DefaultValue::sshUser), sshHost(DefaultValue::sshHost), sshPrivateKeyFile(DefaultValue::sshPrivateKeyFile), @@ -340,6 +341,18 @@ namespace ignite return tlsCaFile.IsSet(); } + bool Configuration::GetSshEnable() const { + return sshEnable.GetValue(); + } + + void Configuration::SetSshEnable(bool val) { + this->sshEnable.SetValue(val); + } + + bool Configuration::IsSshEnableSet() const { + return sshEnable.IsSet(); + } + const std::string& Configuration::GetSshUser() const { return sshUser.GetValue(); diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index 308bb225b..3543986cc 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -47,6 +47,7 @@ namespace ignite const std::string ConnectionStringParser::Key::tls = "tls"; const std::string ConnectionStringParser::Key::tlsAllowInvalidHostnames = "tls_allow_invalid_hostnames"; const std::string ConnectionStringParser::Key::tlsCaFile = "tls_ca_file"; + const std::string ConnectionStringParser::Key::sshEnable = "ssh_enable"; const std::string ConnectionStringParser::Key::sshUser = "ssh_user"; const std::string ConnectionStringParser::Key::sshHost = "ssh_host"; const std::string ConnectionStringParser::Key::sshPrivateKeyFile = "ssh_private_key_file"; @@ -303,6 +304,25 @@ namespace ignite { cfg.SetTlsCaFile(value); } + else if (lKey == Key::sshEnable) + { + + BoolParseResult::Type res = StringToBool(value); + + if (res == BoolParseResult::AI_UNRECOGNIZED) { + if (diag) { + diag->AddStatusRecord( + SqlState::S01S02_OPTION_VALUE_CHANGED, + MakeErrorMessage("Unrecognized bool value. " + "Using default value.", + key, value)); + } + + return; + } + + cfg.SetSshEnable(res == BoolParseResult::AI_TRUE); + } else if (lKey == Key::sshUser) { cfg.SetSshUser(value); diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 6526a38bd..e306b9fb3 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -180,6 +180,11 @@ namespace ignite if (tlsCaFile.IsSet() && !config.IsTlsCaFileSet()) config.SetTlsCaFile(tlsCaFile.GetValue()); + SettableValue sshEnable = ReadDsnBool(dsn, ConnectionStringParser::Key::sshEnable); + + if (sshEnable.IsSet() && !config.IsSshEnableSet()) + config.SetSshEnable(sshEnable.GetValue()); + SettableValue sshUser = ReadDsnString(dsn, ConnectionStringParser::Key::sshUser); if (sshUser.IsSet() && !config.IsSshUserSet()) From 438a2277004179a954ef39adc8aeaf1b46a3a734 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 21 Jan 2022 14:30:37 -0800 Subject: [PATCH 045/165] [AD-522] change from GetSshEnable to IsSshEnable for consistency --- src/odbc/include/ignite/odbc/config/configuration.h | 6 +++--- src/odbc/src/config/configuration.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index 4d71e29c1..8327144df 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -459,11 +459,11 @@ namespace ignite bool IsTlsCaFileSet() const; /** - * Get ssh enable. + * Get SSH enable flag. * - * @return sshEnable. + * @return @true if SSH is enabled. */ - bool GetSshEnable() const; + bool IsSshEnable() const; /** * Set ssh enable. diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 580877b61..7f02db73a 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -322,7 +322,7 @@ namespace ignite return tlsCaFile.IsSet(); } - bool Configuration::GetSshEnable() const { + bool Configuration::IsSshEnable() const { return sshEnable.GetValue(); } From 4a640b750a2cf6f07554e820ca4f225bae491859 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 24 Jan 2022 11:25:12 -0800 Subject: [PATCH 046/165] [AD-522] comment out deprecated readPreference variable start on transitioning from readPreferenceEdit to readPreference combo box --- .../odbc/system/ui/dsn_configuration_window.h | 14 +++++++++----- .../src/system/ui/dsn_configuration_window.cpp | 18 +++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 957a46e2a..235772710 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -71,8 +71,8 @@ namespace ignite APP_NAME_LABEL, LOGIN_TIMEOUT_SEC_EDIT, LOGIN_TIMEOUT_SEC_LABEL, - READ_PREFERENCE_EDIT, READ_PREFERENCE_LABEL, + READ_PREFERENCE_COMBO_BOX, REPLICA_SET_EDIT, REPLICA_SET_LABEL, RETRY_READS_CHECK_BOX, @@ -80,8 +80,8 @@ namespace ignite DEFAULT_FETCH_SIZE_LABEL, PROTOCOL_VERSION_LABEL, PROTOCOL_VERSION_COMBO_BOX, - NESTED_TX_MODE_LABEL, - NESTED_TX_MODE_COMBO_BOX, + //NESTED_TX_MODE_LABEL, + //NESTED_TX_MODE_COMBO_BOX, TLS_CHECK_BOX, TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, TLS_CA_FILE_EDIT, @@ -323,8 +323,12 @@ namespace ignite /** Login Timeout (seconds) label. */ std::auto_ptr loginTimeoutSecLabel; - /** Read preference edit. */ - std::auto_ptr readPreferenceEdit; + /** Nested Read Preference ComboBox **/ + std::auto_ptr readPreferenceComboBox; + + // -AL- remove later + ///** Read preference edit. */ + //std::auto_ptr readPreferenceEdit; /** Read preference label. */ std::auto_ptr readPreferenceLabel; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 9049ab05d..c7cbf0b2e 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -19,7 +19,8 @@ #include #include "ignite/odbc/log.h" -#include "ignite/odbc/ssl_mode.h" +//#include "ignite/odbc/read_preference.h" // causes build errors, comment out momentarily +// #include "ignite/odbc/ssl_mode.h" //TODO remove later #include "ignite/odbc/system/ui/dsn_configuration_window.h" #include "ignite/odbc/config/config_tools.h" @@ -67,7 +68,7 @@ namespace ignite appNameLabel(), appNameEdit(), readPreferenceLabel(), - readPreferenceEdit(), + //readPreferenceEdit(), replicaSetLabel(), replicaSetEdit(), retryReadsCheckBox(), @@ -536,17 +537,20 @@ namespace ignite // rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight // I believe + /* //TODO readPreference val = config.GetReadPreference().c_str(); + val = + readPreferenceLabel = CreateLabel( labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Read preference:", ChildId::READ_PREFERENCE_LABEL); - readPreferenceEdit = CreateEdit( + readPreferenceComboBox = CreateComboBox( editPosX, rowPos, editSizeX, ROW_HEIGHT, - val, ChildId::READ_PREFERENCE_EDIT); + "", ChildId::READ_PREFERENCE_COMBO_BOX); rowPos += INTERVAL + ROW_HEIGHT; - + */ val = config.GetReplicaSet().c_str(); replicaSetLabel = CreateLabel( @@ -797,7 +801,7 @@ namespace ignite std::string replicaSetStr; appNameEdit->GetText(appNameStr); - readPreferenceEdit->GetText(readPreferenceStr); + //readPreferenceEdit->GetText(readPreferenceStr); replicaSetEdit->GetText(replicaSetStr); bool retryReads = retryReadsCheckBox->IsChecked(); @@ -832,7 +836,7 @@ namespace ignite cfg.SetApplicationName(appNameStr); cfg.SetLoginTimeoutSeconds(loginTimeoutSec); - cfg.SetReadPreference(readPreferenceStr); + //cfg.SetReadPreference(readPreferenceStr); cfg.SetReplicaSet(replicaSetStr); cfg.SetRetryReads(retryReads); cfg.SetDefaultFetchSize(fetchSize); From a6f819442aeaf5eaef6d6ca6c3e406004979d4db Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 24 Jan 2022 11:29:43 -0800 Subject: [PATCH 047/165] [AD-522] add SSH enable checkbox, SSH private key passphrase, and SSH private key file * add SSH Enable variable in configuration.h and configuration.cpp * add SSH checkbox in SSH group setting * add SSH private key file edit in SSH group setting * add SSH private key pass phrase in SSH group setting ** SSH private key passphrase label requires double the row height due to the label being long. * make SSH setting items disabled/enabled as SSH enable checkbox is unchecked/checked * save SSH variables to configuration when Ok button is pressed. --- .../ignite/odbc/config/configuration.h | 2 +- .../odbc/system/ui/dsn_configuration_window.h | 4 + .../system/ui/dsn_configuration_window.cpp | 75 +++++++++++++++++-- src/odbc/src/config/configuration.cpp | 12 ++- 4 files changed, 82 insertions(+), 11 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index 8327144df..9e92311f9 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -470,7 +470,7 @@ namespace ignite * * @param bool ssh enable. */ - void SetSshEnable(bool sshEnable); + void SetSshEnable(bool val); /** * Check if the ssh enable value set. diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 235772710..f6e747eef 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -56,6 +56,7 @@ namespace ignite ADDRESS_LABEL, SCHEMA_EDIT, SCHEMA_LABEL, + SSH_ENABLE_CHECK_BOX, SSH_USER_EDIT, SSH_USER_LABEL, SSH_HOST_EDIT, @@ -278,6 +279,9 @@ namespace ignite /** DSN schema edit field. */ std::auto_ptr schemaEdit; + /** SSH enable checkBox. */ + std::auto_ptr sshEnableCheckBox; + /** SSH user edit. */ std::auto_ptr sshUserEdit; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index c7cbf0b2e..ce626cd20 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -53,6 +53,7 @@ namespace ignite schemaLabel(), schemaEdit(), // internal SSH tunnel vars + sshEnableCheckBox(), sshUserLabel(), sshUserEdit(), sshHostLabel(), @@ -127,10 +128,12 @@ namespace ignite int posXRight = MARGIN + (width - MARGIN) / 2; int groupPosYRight = MARGIN; + // create left column group settings groupPosYLeft += INTERVAL + CreateConnectionSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); groupPosYLeft += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); - groupPosYLeft += INTERVAL + CreateSshSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); - groupPosYRight += INTERVAL + CreateSslSettingsGroup(posXRight, groupPosYRight, groupSizeY); + groupPosYLeft += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); + // create right column group settings + groupPosYRight += INTERVAL + CreateSshSettingsGroup(posXRight, groupPosYRight, groupSizeY); groupPosYRight += INTERVAL + CreateAdditionalSettingsGroup(posXRight, groupPosYRight, groupSizeY); //groupPosY += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosY, groupSizeY); //groupPosY += INTERVAL + CreateAdditionalSettingsGroup(MARGIN, groupPosY, groupSizeY); @@ -261,6 +264,12 @@ namespace ignite int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; + sshEnableCheckBox = CreateCheckBox( + labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "Enable SSH Tunnel", + ChildId::SSH_ENABLE_CHECK_BOX, config.IsSshEnable()); + + rowPos += INTERVAL + ROW_HEIGHT; + const char* val = config.GetSshUser().c_str(); sshUserLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSH user :", ChildId::SSH_USER_LABEL); @@ -277,6 +286,25 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; + val = config.GetSshPrivateKeyFile().c_str(); + + sshPrivateKeyFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "SSH private key file :", ChildId::SSH_PRIVATE_KEY_FILE_LABEL); + sshPrivateKeyFileEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, ChildId::SSH_PRIVATE_KEY_FILE_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetSshPrivateKeyPassphrase().c_str(); + + // ssh private key passphrase label requires double the row height due to the long label. + sshPrivateKeyPassphraseLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT * 2, + "SSH private key passphrase :", ChildId::SSH_PRIVATE_KEY_PASSPHRASE_LABEL); + sshPrivateKeyPassphraseEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT * 2, val, ChildId::SSH_PRIVATE_KEY_PASSPHRASE_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT * 2; + sshStrictHostKeyCheckingCheckBox = CreateCheckBox( labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "SSH strict host key checking", ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX, config.IsSshStrictHostKeyChecking()); @@ -296,6 +324,13 @@ namespace ignite "Internal SSH tunnel settings", ChildId::SSH_SETTINGS_GROUP_BOX); + sshUserEdit->SetEnabled(sshEnableCheckBox->IsChecked()); + sshHostEdit->SetEnabled(sshEnableCheckBox->IsChecked()); + sshPrivateKeyFileEdit->SetEnabled( sshEnableCheckBox->IsChecked()); + sshPrivateKeyPassphraseEdit->SetEnabled(sshEnableCheckBox->IsChecked()); + sshStrictHostKeyCheckingCheckBox->SetEnabled(sshEnableCheckBox->IsChecked()); + sshKnownHostsFileEdit->SetEnabled(sshEnableCheckBox->IsChecked()); + return rowPos - posY; } @@ -625,6 +660,25 @@ namespace ignite break; } + case ChildId::SSH_ENABLE_CHECK_BOX: + { + sshEnableCheckBox->SetChecked(!sshEnableCheckBox->IsChecked()); + sshUserEdit->SetEnabled( + sshEnableCheckBox->IsChecked()); + sshHostEdit->SetEnabled(sshEnableCheckBox->IsChecked()); + sshPrivateKeyFileEdit->SetEnabled( + sshEnableCheckBox->IsChecked()); + sshPrivateKeyPassphraseEdit->SetEnabled( + sshEnableCheckBox->IsChecked()); + sshStrictHostKeyCheckingCheckBox + ->SetEnabled( + sshEnableCheckBox->IsChecked()); + sshKnownHostsFileEdit->SetEnabled( + sshEnableCheckBox->IsChecked()); + + break; + } + case ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX: { sshStrictHostKeyCheckingCheckBox @@ -682,6 +736,7 @@ namespace ignite { RetrieveConnectionParameters(cfg); RetrieveAuthParameters(cfg); + RetrieveSshParameters(cfg); RetrieveSslParameters(cfg); RetrieveAdditionalParameters(cfg); } @@ -748,6 +803,9 @@ namespace ignite void DsnConfigurationWindow::RetrieveSshParameters(config::Configuration& cfg) const { + bool sshEnable = sshEnableCheckBox->IsChecked(); + bool sshStrictHostKeyChecking = sshStrictHostKeyCheckingCheckBox->IsChecked(); + std::string sshUserStr; std::string sshHostStr; std::string sshPrivateKeyFileStr; @@ -756,19 +814,24 @@ namespace ignite sshUserEdit->GetText(sshUserStr); sshHostEdit->GetText(sshHostStr); - //sshPrivateKeyFileEdit->GetText(sshPrivateKeyFileStr); - //sshPrivateKeyPassphraseEdit->GetText(sshPrivateKeyPassphraseStr); + sshPrivateKeyFileEdit->GetText(sshPrivateKeyFileStr); + sshPrivateKeyPassphraseEdit->GetText(sshPrivateKeyPassphraseStr); sshKnownHostsFileEdit->GetText(sshKnownHostsFileStr); - bool sshStrictHostKeyChecking = sshStrictHostKeyCheckingCheckBox->IsChecked(); - + LOG_MSG("Retrieving arguments:"); + LOG_MSG("SSH enable: " << (sshEnable ? "true" : "false")); LOG_MSG("SSH user: " << sshUserStr); LOG_MSG("SSH host: " << sshHostStr); + LOG_MSG("SSH private key file: " << sshPrivateKeyFileStr); + LOG_MSG("SSH private key passphrase: " << sshPrivateKeyPassphraseStr); LOG_MSG("SSH known hosts file: " << sshKnownHostsFileStr); LOG_MSG("SSH strict host key checking: " << (sshStrictHostKeyChecking ? "true" : "false")); + cfg.SetSshEnable(sshEnable); cfg.SetSshUser(sshUserStr); cfg.SetSshHost(sshHostStr); + cfg.SetSshPrivateKeyFile(sshPrivateKeyFileStr); + cfg.SetSshPrivateKeyPassphrase(sshPrivateKeyPassphraseStr); cfg.SetSshKnownHostsFile(sshKnownHostsFileStr); cfg.SetSshStrictHostKeyChecking(sshStrictHostKeyChecking); diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 7f02db73a..3d99ca6b9 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -51,7 +51,7 @@ namespace ignite const bool Configuration::DefaultValue::refreshSchema = false; // Internal SSH Tunnel options // need to add to UI - const bool Configuration::DefaultValue::sshEnable = false; + const bool Configuration::DefaultValue::sshEnable = false; const std::string Configuration::DefaultValue::sshUser = ""; const std::string Configuration::DefaultValue::sshHost = ""; const std::string Configuration::DefaultValue::sshPrivateKeyFile = ""; @@ -322,15 +322,18 @@ namespace ignite return tlsCaFile.IsSet(); } - bool Configuration::IsSshEnable() const { + bool Configuration::IsSshEnable() const + { return sshEnable.GetValue(); } - void Configuration::SetSshEnable(bool val) { + void Configuration::SetSshEnable(bool val) + { this->sshEnable.SetValue(val); } - bool Configuration::IsSshEnableSet() const { + bool Configuration::IsSshEnableSet() const + { return sshEnable.IsSet(); } @@ -546,6 +549,7 @@ namespace ignite AddToMap(res, ConnectionStringParser::Key::tls, tls); AddToMap(res, ConnectionStringParser::Key::tlsAllowInvalidHostnames, tlsAllowInvalidHostnames); AddToMap(res, ConnectionStringParser::Key::tlsCaFile, tlsCaFile); + AddToMap(res, ConnectionStringParser::Key::sshEnable, sshEnable); AddToMap(res, ConnectionStringParser::Key::sshUser, sshUser); AddToMap(res, ConnectionStringParser::Key::sshHost, sshHost); AddToMap(res, ConnectionStringParser::Key::sshPrivateKeyFile, sshPrivateKeyFile); From 82c97aeec110aee3afcb3c6357f7c3d511b927a9 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 24 Jan 2022 14:13:03 -0800 Subject: [PATCH 048/165] [AD-522] read_preference.h fix * add guards to read_preference.h fix * include read_preference.h in dsn_configuration_window.cpp * add draft code for read preference in dsn_configuration_window.cpp --- src/odbc/include/ignite/odbc/read_preference.h | 7 ++++++- .../src/system/ui/dsn_configuration_window.cpp | 15 +++++++++++---- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/odbc/include/ignite/odbc/read_preference.h b/src/odbc/include/ignite/odbc/read_preference.h index 2859692b9..7a90f5797 100644 --- a/src/odbc/include/ignite/odbc/read_preference.h +++ b/src/odbc/include/ignite/odbc/read_preference.h @@ -15,6 +15,9 @@ * limitations under the License. */ +#ifndef _IGNITE_ODBC_READ_PREFERENCE +#define _IGNITE_ODBC_READ_PREFERENCE + #include namespace ignite @@ -24,7 +27,7 @@ namespace ignite /** Read Preference enum. */ struct ReadPreference { - enum class Type + enum Type { PRIMARY, @@ -59,3 +62,5 @@ namespace ignite }; } } + +#endif //_IGNITE_ODBC_READ_PREFERENCE \ No newline at end of file diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index ce626cd20..a2e468820 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -19,7 +19,7 @@ #include #include "ignite/odbc/log.h" -//#include "ignite/odbc/read_preference.h" // causes build errors, comment out momentarily +#include "ignite/odbc/read_preference.h" // causes build errors, comment out momentarily // #include "ignite/odbc/ssl_mode.h" //TODO remove later #include "ignite/odbc/system/ui/dsn_configuration_window.h" @@ -69,6 +69,7 @@ namespace ignite appNameLabel(), appNameEdit(), readPreferenceLabel(), + readPreferenceComboBox(), //readPreferenceEdit(), replicaSetLabel(), replicaSetEdit(), @@ -572,10 +573,11 @@ namespace ignite // rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight // I believe - /* //TODO readPreference - val = config.GetReadPreference().c_str(); + /*//TODO readPreference + ReadPreference::Type readPreference = config.GetReadPreference(); + std::string readPreferenceStr = ReadPreference::ToString(readPreference); - val = + const char* val = readPreferenceStr.c_str(); readPreferenceLabel = CreateLabel( labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, @@ -584,6 +586,11 @@ namespace ignite editPosX, rowPos, editSizeX, ROW_HEIGHT, "", ChildId::READ_PREFERENCE_COMBO_BOX); + readPreferenceComboBox->AddString("disable"); + sslModeComboBox->AddString("require"); + + sslModeComboBox->SetSelection(sslMode); // set default + rowPos += INTERVAL + ROW_HEIGHT; */ val = config.GetReplicaSet().c_str(); From 955e7baa8570030c6699f878a4ba5dfc7846e9f2 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 24 Jan 2022 14:18:12 -0800 Subject: [PATCH 049/165] [AD-522] update fields in configuration window * modified order of fields in the configuration window. - Retry reads checkbox is now in the first row under "Additional Settings". - SSH Strict host key check is now in the last row under "Internal SSH Tunnel Settings" - Allow invalid hostnames checkbox now is in 2nd row under "TLS/SSL settings" * added warning sentences for Allow invalid hostnames checkbox and SSH strict host key check --- .../system/ui/dsn_configuration_window.cpp | 122 +++++++++--------- 1 file changed, 59 insertions(+), 63 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index a2e468820..e7c02c5d3 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -125,8 +125,9 @@ namespace ignite { int groupPosYLeft = MARGIN; //int groupSizeY = width - 2 * MARGIN; // original - int groupSizeY = (width - 2 * MARGIN) / 2; + int groupSizeY = width / 2 - 2 * MARGIN; int posXRight = MARGIN + (width - MARGIN) / 2; + //int posXRight = MARGIN + groupSizeY; int groupPosYRight = MARGIN; // create left column group settings @@ -183,15 +184,15 @@ namespace ignite val = config.GetDatabase().c_str(); schemaLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Schema name:", ChildId::SCHEMA_LABEL); + "Schema Name:", ChildId::SCHEMA_LABEL); schemaEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SCHEMA_EDIT); rowPos += INTERVAL + ROW_HEIGHT; protocolVersionLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Protocol version:", ChildId::PROTOCOL_VERSION_LABEL); + "Protocol Version:", ChildId::PROTOCOL_VERSION_LABEL); protocolVersionComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, - "Protocol version", ChildId::PROTOCOL_VERSION_COMBO_BOX); + "Protocol Version", ChildId::PROTOCOL_VERSION_COMBO_BOX); int id = 0; @@ -215,7 +216,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; connectionSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "Connection settings", ChildId::CONNECTION_SETTINGS_GROUP_BOX); + "Connection Settings", ChildId::CONNECTION_SETTINGS_GROUP_BOX); return rowPos - posY; } @@ -232,7 +233,6 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; const char* val = config.GetUser().c_str(); - userLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "User :", ChildId::USER_LABEL); userEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::USER_EDIT); @@ -247,7 +247,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; authSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "Authentication settings", ChildId::AUTH_SETTINGS_GROUP_BOX); + "Authentication Settings", ChildId::AUTH_SETTINGS_GROUP_BOX); return rowPos - posY; } @@ -263,7 +263,8 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; - int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; + //int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; // original + int checkBoxSize = sizeX - 2 * MARGIN; sshEnableCheckBox = CreateCheckBox( labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "Enable SSH Tunnel", @@ -272,65 +273,60 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; const char* val = config.GetSshUser().c_str(); - - sshUserLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSH user :", ChildId::SSH_USER_LABEL); + sshUserLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSH User :", ChildId::SSH_USER_LABEL); sshUserEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_USER_EDIT); rowPos += INTERVAL + ROW_HEIGHT; val = config.GetSshHost().c_str(); - sshHostLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSH host :", ChildId::SSH_HOST_LABEL); + "SSH Hostname :", ChildId::SSH_HOST_LABEL); sshHostEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_HOST_EDIT); rowPos += INTERVAL + ROW_HEIGHT; val = config.GetSshPrivateKeyFile().c_str(); - sshPrivateKeyFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSH private key file :", ChildId::SSH_PRIVATE_KEY_FILE_LABEL); + "SSH Private Key File :", ChildId::SSH_PRIVATE_KEY_FILE_LABEL); sshPrivateKeyFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_PRIVATE_KEY_FILE_EDIT); rowPos += INTERVAL + ROW_HEIGHT; val = config.GetSshPrivateKeyPassphrase().c_str(); - // ssh private key passphrase label requires double the row height due to the long label. sshPrivateKeyPassphraseLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT * 2, - "SSH private key passphrase :", ChildId::SSH_PRIVATE_KEY_PASSPHRASE_LABEL); + "SSH Private Key Passphrase :", ChildId::SSH_PRIVATE_KEY_PASSPHRASE_LABEL); sshPrivateKeyPassphraseEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT * 2, val, ChildId::SSH_PRIVATE_KEY_PASSPHRASE_EDIT); rowPos += INTERVAL + ROW_HEIGHT * 2; - sshStrictHostKeyCheckingCheckBox = CreateCheckBox( - labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "SSH strict host key checking", - ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX, config.IsSshStrictHostKeyChecking()); - - rowPos += INTERVAL + ROW_HEIGHT; - val = config.GetSshKnownHostsFile().c_str(); - sshKnownHostsFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSH known hosts:", ChildId::SSH_KNOWN_HOSTS_FILE_LABEL); + "SSH Known Hosts:", ChildId::SSH_KNOWN_HOSTS_FILE_LABEL); sshKnownHostsFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_KNOWN_HOSTS_FILE_EDIT); + rowPos += INTERVAL + ROW_HEIGHT; + // SSH Strict Host Key Check check box needs to have editSizeX as size because the string is long + sshStrictHostKeyCheckingCheckBox = CreateCheckBox( + labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "SSH Strict Host Key Check (disabling option is less secure)", + ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX, config.IsSshStrictHostKeyChecking()); + rowPos += INTERVAL + ROW_HEIGHT; sshSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "Internal SSH tunnel settings", + "Internal SSH Tunnel Settings", ChildId::SSH_SETTINGS_GROUP_BOX); sshUserEdit->SetEnabled(sshEnableCheckBox->IsChecked()); sshHostEdit->SetEnabled(sshEnableCheckBox->IsChecked()); sshPrivateKeyFileEdit->SetEnabled( sshEnableCheckBox->IsChecked()); sshPrivateKeyPassphraseEdit->SetEnabled(sshEnableCheckBox->IsChecked()); - sshStrictHostKeyCheckingCheckBox->SetEnabled(sshEnableCheckBox->IsChecked()); sshKnownHostsFileEdit->SetEnabled(sshEnableCheckBox->IsChecked()); + sshStrictHostKeyCheckingCheckBox->SetEnabled(sshEnableCheckBox->IsChecked()); return rowPos - posY; } @@ -392,14 +388,16 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; - int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; + //int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; // original + int checkBoxSize = sizeX - 2 * MARGIN; tlsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "TLS", ChildId::TLS_CHECK_BOX, config.IsTls()); + "Enable TLS", ChildId::TLS_CHECK_BOX, config.IsTls()); + + rowPos += INTERVAL + ROW_HEIGHT; tlsAllowInvalidHostnamesCheckBox = CreateCheckBox( - labelPosX + checkBoxSize + INTERVAL, rowPos, - checkBoxSize, ROW_HEIGHT, "TLS Allow Invalid Hostnames", + labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "Allow Invalid Hostnames (enabling option is less secure)", ChildId::TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, config.IsTlsAllowInvalidHostnames()); @@ -414,7 +412,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "TLS/SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); + "TLS/SSL Settings", ChildId::SSL_SETTINGS_GROUP_BOX); tlsAllowInvalidHostnamesCheckBox->SetEnabled(tlsCheckBox->IsChecked()); tlsCaFileEdit->SetEnabled(tlsCheckBox->IsChecked()); @@ -528,28 +526,10 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; - const char* val = config.GetApplicationName().c_str(); - - appNameLabel = CreateLabel( - labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Application Name:", ChildId::APP_NAME_LABEL); - appNameEdit = - CreateEdit(editPosX, rowPos, editSizeX, - ROW_HEIGHT, val, - ChildId::APP_NAME_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - - std::string tmp = common::LexicalCast< std::string >( - config.GetLoginTimeoutSeconds()); - val = tmp.c_str(); - loginTimeoutSecLabel = CreateLabel( - labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Login Timeout (s):", ChildId::LOGIN_TIMEOUT_SEC_LABEL); - - loginTimeoutSecEdit = CreateEdit( - editPosX, rowPos, editSizeX, ROW_HEIGHT, - val, ChildId::LOGIN_TIMEOUT_SEC_EDIT, ES_NUMBER); + retryReadsCheckBox = CreateCheckBox( + labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, + "Retry Reads", ChildId::RETRY_READS_CHECK_BOX, + config.IsRetryReads()); rowPos += INTERVAL + ROW_HEIGHT; @@ -593,8 +573,31 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; */ - val = config.GetReplicaSet().c_str(); + const char* val = config.GetApplicationName().c_str(); + appNameLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Application Name:", ChildId::APP_NAME_LABEL); + appNameEdit = + CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, + ChildId::APP_NAME_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + std::string tmp = common::LexicalCast< std::string >( + config.GetLoginTimeoutSeconds()); + val = tmp.c_str(); + loginTimeoutSecLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Login Timeout (s):", ChildId::LOGIN_TIMEOUT_SEC_LABEL); + + loginTimeoutSecEdit = + CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, + ChildId::LOGIN_TIMEOUT_SEC_EDIT, ES_NUMBER); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetReplicaSet().c_str(); replicaSetLabel = CreateLabel( labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Replica Set:", ChildId::REPLICA_SET_LABEL); @@ -605,19 +608,12 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - retryReadsCheckBox = CreateCheckBox( - labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Retry Reads", ChildId::RETRY_READS_CHECK_BOX, - config.IsRetryReads()); - - rowPos += INTERVAL + ROW_HEIGHT; - tmp = common::LexicalCast< std::string >( config.GetDefaultFetchSize()); val = tmp.c_str(); defaultFetchSizeLabel = CreateLabel( labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Fetch size:", ChildId::DEFAULT_FETCH_SIZE_LABEL); + "Fetch Size:", ChildId::DEFAULT_FETCH_SIZE_LABEL); defaultFetchSizeEdit = CreateEdit( editPosX, rowPos, editSizeX, ROW_HEIGHT, @@ -626,7 +622,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; additionalSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, - rowPos - posY, "Additional settings", + rowPos - posY, "Additional Settings", ChildId::ADDITIONAL_SETTINGS_GROUP_BOX); return rowPos - posY; From 2f4b10878d22ecbfff1ce0c66ac7ba931dd3744f Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Mon, 24 Jan 2022 14:34:39 -0800 Subject: [PATCH 050/165] Improvements from code review + address some warnings --- src/odbc-test/CMakeLists.txt | 20 ++-- src/odbc-test/src/configuration_test.cpp | 34 +++---- .../ignite/odbc/config/configuration.h | 64 ++++++------- .../odbc/config/connection_string_parser.h | 4 +- src/odbc/include/ignite/odbc/connection.h | 1 + .../include/ignite/odbc/read_preference.h | 23 +++-- src/odbc/include/ignite/odbc/scan_method.h | 23 +++-- src/odbc/src/config/configuration.cpp | 42 +------- .../src/config/connection_string_parser.cpp | 78 ++++++++------- src/odbc/src/connection.cpp | 95 +++---------------- src/odbc/src/dsn_config.cpp | 4 +- src/odbc/src/read_preference.cpp | 23 +++-- src/odbc/src/scan_method.cpp | 23 +++-- 13 files changed, 171 insertions(+), 263 deletions(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index dcee91837..e947b1f31 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -37,26 +37,30 @@ else () endif() set(SOURCES + src/configuration_test.cpp src/connection_test.cpp src/dummy_test.cpp src/odbc_test_suite.cpp - src/test_utils.cpp + src/test_utils.cpp + ../odbc/src/app/application_data_buffer.cpp + ../odbc/src/common_types.cpp + ../odbc/src/common/big_integer.cpp + ../odbc/src/common/bits.cpp ../odbc/src/common/concurrent.cpp + ../odbc/src/common/decimal.cpp ../odbc/src/common/utils.cpp - ../odbc/src/jni/java.cpp - src/configuration_test.cpp ../odbc/src/config/config_tools.cpp ../odbc/src/config/configuration.cpp ../odbc/src/config/connection_info.cpp ../odbc/src/config/connection_string_parser.cpp - ../odbc/src/scan_method.cpp - ../odbc/src/read_preference.cpp ../odbc/src/diagnostic/diagnostic_record.cpp ../odbc/src/diagnostic/diagnostic_record_storage.cpp - ../odbc/src/utility.cpp - ../odbc/src/common_types.cpp - ../odbc/src/app/application_data_buffer.cpp + ../odbc/src/ignite_error.cpp + ../odbc/src/jni/java.cpp ../odbc/src/log.cpp + ../odbc/src/read_preference.cpp + ../odbc/src/scan_method.cpp + ../odbc/src/utility.cpp # TODO uncomment/rework the tests after get some connectivity and functionalities working. # src/teamcity/teamcity_boost.cpp # src/teamcity/teamcity_messages.cpp diff --git a/src/odbc-test/src/configuration_test.cpp b/src/odbc-test/src/configuration_test.cpp index d2c441280..f4be22152 100644 --- a/src/odbc-test/src/configuration_test.cpp +++ b/src/odbc-test/src/configuration_test.cpp @@ -112,7 +112,7 @@ void CheckValidAddress(const char* connectStr, const EndPoint& endPoint) ParseValidConnectString(connectStr, cfg); BOOST_CHECK_EQUAL(cfg.GetHostname(), endPoint.host); - BOOST_CHECK_EQUAL(cfg.GetTcpPort(), endPoint.port); + BOOST_CHECK_EQUAL(cfg.GetPort(), endPoint.port); } void CheckValidScanMethod(const char* connectStr, ScanMethod::Type scanMethod) @@ -184,7 +184,7 @@ void CheckConnectionConfig(const Configuration& cfg) BOOST_CHECK_EQUAL(cfg.GetDriver(), testDriverName); BOOST_CHECK_EQUAL(cfg.GetDatabase(), testDatabaseName); BOOST_CHECK_EQUAL(cfg.GetHostname(), testHostname); - BOOST_CHECK_EQUAL(cfg.GetTcpPort(), testServerPort); + BOOST_CHECK_EQUAL(cfg.GetPort(), testServerPort); BOOST_CHECK_EQUAL(cfg.GetUser(), testUsername); BOOST_CHECK_EQUAL(cfg.GetPassword(), testPassword); BOOST_CHECK_EQUAL(cfg.GetApplicationName(), testAppName); @@ -247,7 +247,7 @@ void CheckDsnConfig(const Configuration& cfg) BOOST_CHECK_EQUAL(cfg.GetDsn(), testDsn); BOOST_CHECK_EQUAL(cfg.GetDatabase(), Configuration::DefaultValue::database); BOOST_CHECK_EQUAL(cfg.GetHostname(), Configuration::DefaultValue::hostname); - BOOST_CHECK_EQUAL(cfg.GetTcpPort(), Configuration::DefaultValue::port); + BOOST_CHECK_EQUAL(cfg.GetPort(), Configuration::DefaultValue::port); BOOST_CHECK_EQUAL(cfg.GetUser(), Configuration::DefaultValue::user); BOOST_CHECK_EQUAL(cfg.GetPassword(), Configuration::DefaultValue::password); BOOST_CHECK_EQUAL(cfg.GetApplicationName(), Configuration::DefaultValue::appName); @@ -554,17 +554,17 @@ BOOST_AUTO_TEST_CASE(TestConnectStringValidReadPreference) BOOST_AUTO_TEST_CASE(TestConnectStringInvalidBoolKeys) { - typedef std::set Set; + using Set = std::set>; Set keys; - keys.insert("retry_reads"); - keys.insert("tls"); - keys.insert("tls_allow_invalid_hostnames"); - keys.insert("ssh_strict_host_key_checking"); - keys.insert("refresh_schema"); + keys.emplace("retry_reads"); + keys.emplace("tls"); + keys.emplace("tls_allow_invalid_hostnames"); + keys.emplace("ssh_strict_host_key_checking"); + keys.emplace("refresh_schema"); - for (Set::const_iterator it = keys.begin(); it != keys.end(); ++it) + for (auto it = keys.begin(); it != keys.end(); ++it) { const std::string& key = *it; @@ -581,17 +581,17 @@ BOOST_AUTO_TEST_CASE(TestConnectStringInvalidBoolKeys) BOOST_AUTO_TEST_CASE(TestConnectStringValidBoolKeys) { - typedef std::set Set; + using Set = std::set>; Set keys; - keys.insert("retry_reads"); - keys.insert("tls"); - keys.insert("tls_allow_invalid_hostnames"); - keys.insert("ssh_strict_host_key_checking"); - keys.insert("refresh_schema"); + keys.emplace("retry_reads"); + keys.emplace("tls"); + keys.emplace("tls_allow_invalid_hostnames"); + keys.emplace("ssh_strict_host_key_checking"); + keys.emplace("refresh_schema"); - for (Set::const_iterator it = keys.begin(); it != keys.end(); ++it) + for (auto it = keys.begin(); it != keys.end(); ++it) { const std::string& key = *it; diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index ee52f697c..4d3908598 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -133,12 +133,12 @@ namespace ignite /** * Default constructor. */ - Configuration(); + Configuration() = default; /** * Destructor. */ - ~Configuration(); + ~Configuration() = default; /** * Convert configure to connect string. @@ -208,21 +208,21 @@ namespace ignite * * @return Server port. */ - uint16_t GetTcpPort() const; + uint16_t GetPort() const; /** * Set server port. * * @param portNumber Server port. */ - void SetTcpPort(uint16_t portNumber); + void SetPort(uint16_t portNumber); /** * Check if the value set. * * @return @true if the value set. */ - bool IsTcpPortSet() const; + bool IsPortSet() const; /** * Get database. @@ -705,82 +705,82 @@ namespace ignite static void AddToMap(ArgumentMap& map, const std::string& key, const SettableValue& value); /** DSN. */ - SettableValue dsn; + SettableValue dsn = DefaultValue::dsn; /** Driver name. */ - SettableValue driver; + SettableValue driver = DefaultValue::driver; /** Schema. */ - SettableValue database; + SettableValue database = DefaultValue::database; /** Hostname. */ - SettableValue hostname; + SettableValue hostname = DefaultValue::hostname; /** Port. */ - SettableValue port; + SettableValue port = DefaultValue::port; /** User. */ - SettableValue user; + SettableValue user = DefaultValue::user; /** Password. */ - SettableValue password; + SettableValue password = DefaultValue::password; /** Application name. */ - SettableValue appName; + SettableValue appName = DefaultValue::appName; /** Login timeout in seconds. */ - SettableValue loginTimeoutSec; + SettableValue loginTimeoutSec = DefaultValue::loginTimeoutSec; /** Read pereference. */ - SettableValue readPreference; + SettableValue readPreference = DefaultValue::readPreference; /** Replica set name. */ - SettableValue replicaSet; + SettableValue replicaSet = DefaultValue::replicaSet; /** Retry reads flag. */ - SettableValue retryReads; + SettableValue retryReads = DefaultValue::retryReads; /** Enable SSL/TLS. */ - SettableValue tls; + SettableValue tls = DefaultValue::tls; /** Flag for if invalid hostnames for the TLS certificate are allowed. */ - SettableValue tlsAllowInvalidHostnames; + SettableValue tlsAllowInvalidHostnames = DefaultValue::tlsAllowInvalidHostnames; /** SSL/TLS certificate authority file path. */ - SettableValue tlsCaFile; + SettableValue tlsCaFile = DefaultValue::tlsCaFile; /** The SSH host username for the internal SSH tunnel. */ - SettableValue sshUser; + SettableValue sshUser = DefaultValue::sshUser; /** The SSH host host name for the internal SSH tunnel. */ - SettableValue sshHost; + SettableValue sshHost = DefaultValue::sshHost; /** The SSH host private key file path for the internal SSH tunnel. */ - SettableValue sshPrivateKeyFile; + SettableValue sshPrivateKeyFile = DefaultValue::sshPrivateKeyFile; /** The SSH host private key file passphrase for the internal SSH tunnel. */ - SettableValue sshPrivateKeyPassphrase; + SettableValue sshPrivateKeyPassphrase = DefaultValue::sshPrivateKeyPassphrase; /** Strict host key checking flag for the internal SSH tunnel. */ - SettableValue sshStrictHostKeyChecking; + SettableValue sshStrictHostKeyChecking = DefaultValue::sshStrictHostKeyChecking; /** The known hosts file path for the internal SSH tunnel. */ - SettableValue sshKnownHostsFile; + SettableValue sshKnownHostsFile = DefaultValue::sshKnownHostsFile; /** Scan method. */ - SettableValue scanMethod; + SettableValue scanMethod = DefaultValue::scanMethod; /** Scan limit. */ - SettableValue scanLimit; + SettableValue scanLimit = DefaultValue::scanLimit; /** Schema name. */ - SettableValue schemaName; + SettableValue schemaName = DefaultValue::schemaName; /** Refresh schema flag. */ - SettableValue refreshSchema; + SettableValue refreshSchema = DefaultValue::refreshSchema; - /** Request and response page size. */ - SettableValue defaultFetchSize; + /** Default fetch size. */ + SettableValue defaultFetchSize = DefaultValue::defaultFetchSize; }; template<> diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index 16b02d484..42469d026 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -145,7 +145,7 @@ namespace ignite /** * Destructor. */ - ~ConnectionStringParser(); + ~ConnectionStringParser() = default; /** * Parse connect string. @@ -180,7 +180,7 @@ namespace ignite */ struct BoolParseResult { - enum Type + enum class Type { AI_FALSE, diff --git a/src/odbc/include/ignite/odbc/connection.h b/src/odbc/include/ignite/odbc/connection.h index 0a917a50d..d35b1ad40 100644 --- a/src/odbc/include/ignite/odbc/connection.h +++ b/src/odbc/include/ignite/odbc/connection.h @@ -31,6 +31,7 @@ #include "ignite/odbc/streaming/streaming_context.h" #include "ignite/odbc/odbc_error.h" #include "ignite/odbc/jni/java.h" +#include "ignite/odbc/end_point.h" namespace ignite { diff --git a/src/odbc/include/ignite/odbc/read_preference.h b/src/odbc/include/ignite/odbc/read_preference.h index 2859692b9..3ab19dcce 100644 --- a/src/odbc/include/ignite/odbc/read_preference.h +++ b/src/odbc/include/ignite/odbc/read_preference.h @@ -1,18 +1,17 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Copyright <2022> Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include diff --git a/src/odbc/include/ignite/odbc/scan_method.h b/src/odbc/include/ignite/odbc/scan_method.h index 1feb2f9ca..0267bdec2 100644 --- a/src/odbc/include/ignite/odbc/scan_method.h +++ b/src/odbc/include/ignite/odbc/scan_method.h @@ -1,18 +1,17 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Copyright <2022> Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index d6a6e2cb9..9b66df00d 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -66,42 +66,6 @@ namespace ignite const bool Configuration::DefaultValue::retryReads = true; const int32_t Configuration::DefaultValue::defaultFetchSize = 2000; - Configuration::Configuration() : - dsn(DefaultValue::dsn), - driver(DefaultValue::driver), - database(DefaultValue::database), - hostname(DefaultValue::hostname), - port(DefaultValue::port), - user(DefaultValue::user), - password(DefaultValue::password), - appName(DefaultValue::appName), - loginTimeoutSec(DefaultValue::loginTimeoutSec), - readPreference(DefaultValue::readPreference), - replicaSet(DefaultValue::replicaSet), - retryReads(DefaultValue::retryReads), - tls(DefaultValue::tls), - tlsAllowInvalidHostnames(DefaultValue::tlsAllowInvalidHostnames), - tlsCaFile(DefaultValue::tlsCaFile), - sshUser(DefaultValue::sshUser), - sshHost(DefaultValue::sshHost), - sshPrivateKeyFile(DefaultValue::sshPrivateKeyFile), - sshPrivateKeyPassphrase(DefaultValue::sshPrivateKeyPassphrase), - sshStrictHostKeyChecking(DefaultValue::sshStrictHostKeyChecking), - sshKnownHostsFile(DefaultValue::sshKnownHostsFile), - scanMethod(DefaultValue::scanMethod), - scanLimit(DefaultValue::scanLimit), - schemaName(DefaultValue::schemaName), - refreshSchema(DefaultValue::refreshSchema), - defaultFetchSize(DefaultValue::defaultFetchSize) - { - // No-op. - } - - Configuration::~Configuration() - { - // No-op. - } - std::string Configuration::ToConnectString() const { ArgumentMap arguments; @@ -127,17 +91,17 @@ namespace ignite return connect_string_buffer.str(); } - uint16_t Configuration::GetTcpPort() const + uint16_t Configuration::GetPort() const { return port.GetValue(); } - void Configuration::SetTcpPort(uint16_t portNumber) + void Configuration::SetPort(uint16_t portNumber) { this->port.SetValue(portNumber); } - bool Configuration::IsTcpPortSet() const + bool Configuration::IsPortSet() const { return port.IsSet(); } diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index b6e7908fc..8882792b2 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -20,10 +20,8 @@ #include "ignite/common/utils.h" #include "ignite/odbc/utility.h" -//#include "ignite/odbc/ssl_mode.h" #include "ignite/odbc/config/connection_string_parser.h" #include "ignite/odbc/config/config_tools.h" -//#include "ignite/odbc/nested_tx_mode.h" namespace ignite { @@ -66,11 +64,6 @@ namespace ignite // No-op. } - ConnectionStringParser::~ConnectionStringParser() - { - // No-op. - } - void ConnectionStringParser::ParseConnectionString(const char* str, size_t len, char delimiter, diagnostic::DiagnosticRecordStorage* diag) { @@ -158,8 +151,8 @@ namespace ignite cfg.SetHostname(endpoint.host); - if (!cfg.IsTcpPortSet()) - cfg.SetTcpPort(endpoint.port); + if (!cfg.IsPortSet()) + cfg.SetPort(endpoint.port); } else if (lKey == Key::port) { @@ -203,7 +196,7 @@ namespace ignite conv << value; conv >> numValue; - if (numValue <= 0 || numValue > 0xFFFF) + if (numValue <= 0 || numValue > UINT16_MAX) { if (diag) { @@ -215,7 +208,7 @@ namespace ignite return; } - cfg.SetTcpPort(static_cast(numValue)); + cfg.SetPort(static_cast(numValue)); } else if (lKey == Key::appName) { @@ -235,13 +228,24 @@ namespace ignite return; } + if (value.size() >= sizeof("4294967295")) + { + if (diag) + { + diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, + MakeErrorMessage("Login timeout seconds attribute value is too large. Using default value.", key, value)); + } + + return; + } + int64_t numValue = 0; std::stringstream conv; conv << value; conv >> numValue; - if (numValue <= 0 || numValue > 0xFFFFFFFFL) + if (numValue <= 0 || numValue > UINT32_MAX) { if (diag) { @@ -280,7 +284,7 @@ namespace ignite { BoolParseResult::Type res = StringToBool(value); - if (res == BoolParseResult::AI_UNRECOGNIZED) + if (res == BoolParseResult::Type::AI_UNRECOGNIZED) { if (diag) { @@ -291,13 +295,13 @@ namespace ignite return; } - cfg.SetRetryReads(res == BoolParseResult::AI_TRUE); + cfg.SetRetryReads(res == BoolParseResult::Type::AI_TRUE); } else if (lKey == Key::tls) { BoolParseResult::Type res = StringToBool(value); - if (res == BoolParseResult::AI_UNRECOGNIZED) + if (res == BoolParseResult::Type::AI_UNRECOGNIZED) { if (diag) { @@ -308,13 +312,13 @@ namespace ignite return; } - cfg.SetTls(res == BoolParseResult::AI_TRUE); + cfg.SetTls(res == BoolParseResult::Type::AI_TRUE); } else if (lKey == Key::tlsAllowInvalidHostnames) { BoolParseResult::Type res = StringToBool(value); - if (res == BoolParseResult::AI_UNRECOGNIZED) + if (res == BoolParseResult::Type::AI_UNRECOGNIZED) { if (diag) { @@ -325,7 +329,7 @@ namespace ignite return; } - cfg.SetTlsAllowInvalidHostnames(res == BoolParseResult::AI_TRUE); + cfg.SetTlsAllowInvalidHostnames(res == BoolParseResult::Type::AI_TRUE); } else if (lKey == Key::tlsCaFile) { @@ -351,7 +355,7 @@ namespace ignite { BoolParseResult::Type res = StringToBool(value); - if (res == BoolParseResult::AI_UNRECOGNIZED) + if (res == BoolParseResult::Type::AI_UNRECOGNIZED) { if (diag) { @@ -362,7 +366,7 @@ namespace ignite return; } - cfg.SetSshStrictHostKeyChecking(res == BoolParseResult::AI_TRUE); + cfg.SetSshStrictHostKeyChecking(res == BoolParseResult::Type::AI_TRUE); } else if (lKey == Key::sshKnownHostsFile) { @@ -399,13 +403,25 @@ namespace ignite return; } + if (value.size() >= sizeof("4294967295")) + { + if (diag) + { + diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, + MakeErrorMessage("Default fetch size attribute value is too large." + " Using default value.", key, value)); + } + + return; + } + int64_t numValue = 0; std::stringstream conv; conv << value; conv >> numValue; - if (numValue <= 0 || numValue > 0xFFFFFFFFL) + if (numValue <= 0 || numValue > UINT32_MAX) { if (diag) { @@ -427,7 +443,7 @@ namespace ignite { BoolParseResult::Type res = StringToBool(value); - if (res == BoolParseResult::AI_UNRECOGNIZED) + if (res == BoolParseResult::Type::AI_UNRECOGNIZED) { if (diag) { @@ -438,7 +454,7 @@ namespace ignite return; } - cfg.SetRefreshSchema(res == BoolParseResult::AI_TRUE); + cfg.SetRefreshSchema(res == BoolParseResult::Type::AI_TRUE); } else if (lKey == Key::defaultFetchSize) { @@ -459,7 +475,7 @@ namespace ignite if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Page size attribute value is too large." + MakeErrorMessage("Default fetch size attribute value is too large." " Using default value.", key, value)); } @@ -472,12 +488,12 @@ namespace ignite conv << value; conv >> numValue; - if (numValue <= 0 || numValue > 0xFFFFFFFFL) + if (numValue <= 0 || numValue > UINT32_MAX) { if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Page size attribute value is out of range." + MakeErrorMessage("Default fetch size attribute value is out of range." " Using default value.", key, value)); } @@ -486,10 +502,6 @@ namespace ignite cfg.SetDefaultFetchSize(static_cast(numValue)); } - else if (lKey == Key::tlsCaFile) - { - cfg.SetTlsCaFile(value); - } else if (lKey == Key::driver) { cfg.SetDriver(value); @@ -529,12 +541,12 @@ namespace ignite std::string lower = common::ToLower(value); if (lower == "true") - return BoolParseResult::AI_TRUE; + return BoolParseResult::Type::AI_TRUE; if (lower == "false") - return BoolParseResult::AI_FALSE; + return BoolParseResult::Type::AI_FALSE; - return BoolParseResult::AI_UNRECOGNIZED; + return BoolParseResult::Type::AI_UNRECOGNIZED; } std::string ConnectionStringParser::MakeErrorMessage(const std::string& msg, const std::string& key, diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index 280a425c2..643875737 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -146,38 +146,6 @@ namespace ignite IGNITE_ODBC_API_CALL(InternalEstablish(cfg)); } - SqlResult::Type Connection::InitSocket() - { - // Removed SSL Mode in DSN. Replaced this with REQUIRE for now. - ssl::SslMode::Type sslMode = ssl::SslMode::REQUIRE; - - if (sslMode == ssl::SslMode::DISABLE) - { - socket.reset(network::ssl::MakeTcpSocketClient()); - - return SqlResult::AI_SUCCESS; - } - - try - { - network::ssl::EnsureSslLoaded(); - } - catch (const IgniteError &err) - { - LOG_MSG("Can not load OpenSSL library: " << err.GetText()); - - AddStatusRecord("Can not load OpenSSL library (did you set OPENSSL_HOME environment variable?)"); - - return SqlResult::AI_ERROR; - } - - // Removed SSL key and cert files from DSN. Replaced with empty string for now. - socket.reset(network::ssl::MakeSecureSocketClient( - "", "", config.GetTlsCaFile())); - - return SqlResult::AI_SUCCESS; - } - SqlResult::Type Connection::InternalEstablish(const config::Configuration& cfg) { using ssl::SslMode; @@ -553,25 +521,6 @@ namespace ignite SqlResult::Type Connection::MakeRequestHandshake() { - /* ProtocolVersion protocolVersion = config.GetProtocolVersion(); - - if (!protocolVersion.IsSupported()) - { - AddStatusRecord(SqlState::S01S00_INVALID_CONNECTION_STRING_ATTRIBUTE, - "Protocol version is not supported: " + protocolVersion.ToString()); - - return SqlResult::AI_ERROR; - } - - if (protocolVersion < ProtocolVersion::VERSION_2_5_0 && !config.GetUser().empty()) - { - AddStatusRecord(SqlState::S01S00_INVALID_CONNECTION_STRING_ATTRIBUTE, - "Authentication is not allowed for protocol version below 2.5.0"); - - return SqlResult::AI_ERROR; - } - */ - HandshakeRequest req(config); HandshakeResponse rsp; @@ -613,13 +562,6 @@ namespace ignite if (!rsp.GetError().empty()) constructor << "Additional info: " << rsp.GetError() << " "; - /* constructor - << "Current version of the protocol, used by the server " - "node is " - << rsp.GetCurrentVer().ToString() << ", " - << "driver protocol version introduced in version " - << protocolVersion.ToString() << "."; */ - AddStatusRecord(SqlState::S08004_CONNECTION_REJECTED, constructor.str()); return SqlResult::AI_ERROR; @@ -697,19 +639,23 @@ namespace ignite std::string Connection::FormatJdbcConnectionString() const { std::string host = "localhost"; - std::string port = "27017"; - if (!config.GetAddresses().empty()) { - host = config.GetAddresses()[0].host; - port = std::to_string(config.GetAddresses()[0].port); - } + uint16_t port = 27017; std::string jdbConnectionString; + if (config.IsHostnameSet()) { + host = config.GetHostname(); + } + + if (config.IsPortSet()) { + port = config.GetPort(); + } + jdbConnectionString = "jdbc:documentdb:"; jdbConnectionString.append("//" + config.GetUser()); jdbConnectionString.append(":" + config.GetPassword()); jdbConnectionString.append("@" + host); jdbConnectionString.append(":" + port); - jdbConnectionString.append("/" + config.GetSchema()); + jdbConnectionString.append("/" + config.GetDatabase()); jdbConnectionString.append("?tlsAllowInvalidHostnames=true"); // Check if internal SSH tunnel should be enabled. @@ -738,7 +684,7 @@ namespace ignite return jdbConnectionString; } - /** + /** * Create JVM options from configuration. * * @param cfg Configuration. @@ -805,25 +751,10 @@ namespace ignite { endPoints.clear(); - // DocumentDB driver is currently not supporting list of addresses. Always use this 'legacy' method. + // DocumentDB driver is currently not supporting list of addresses. Return vector with the one address for now. LOG_MSG("'Address' is not set. Using legacy connection method."); - endPoints.push_back(EndPoint(cfg.GetHostname(), cfg.GetTcpPort())); + endPoints.push_back(EndPoint(cfg.GetHostname(), cfg.GetPort())); return; - - /*if (!cfg.IsAddressesSet()) - { - LOG_MSG("'Address' is not set. Using legacy connection method."); - - endPoints.push_back(EndPoint(cfg.GetHostname(), cfg.GetTcpPort())); - - return; - } - - endPoints = cfg.GetAddresses(); - - - std::random_shuffle(endPoints.begin(), endPoints.end()); - */ } int32_t Connection::RetrieveTimeout(void* value) diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 9b2b7ac91..810fde66a 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -111,8 +111,8 @@ namespace ignite SettableValue port = ReadDsnInt(dsn, ConnectionStringParser::Key::port); - if (port.IsSet() && !config.IsTcpPortSet()) - config.SetTcpPort(static_cast(port.GetValue())); + if (port.IsSet() && !config.IsPortSet()) + config.SetPort(static_cast(port.GetValue())); SettableValue database = ReadDsnString(dsn, ConnectionStringParser::Key::database); diff --git a/src/odbc/src/read_preference.cpp b/src/odbc/src/read_preference.cpp index 43d81c4dc..ad955b57c 100644 --- a/src/odbc/src/read_preference.cpp +++ b/src/odbc/src/read_preference.cpp @@ -1,18 +1,17 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Copyright <2022> Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include diff --git a/src/odbc/src/scan_method.cpp b/src/odbc/src/scan_method.cpp index 06400dd9a..b9f4ee09b 100644 --- a/src/odbc/src/scan_method.cpp +++ b/src/odbc/src/scan_method.cpp @@ -1,18 +1,17 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Copyright <2022> Amazon.com, Inc. or its affiliates. All Rights Reserved. * - * http://www.apache.org/licenses/LICENSE-2.0 + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ #include From 095edf18b03dcba5cd08ddd0356d95828fc9dfe3 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Mon, 24 Jan 2022 15:14:12 -0800 Subject: [PATCH 051/165] Change connection _test to use hostname key instead of address --- src/odbc-test/src/configuration_test.cpp | 4 ++-- src/odbc-test/src/connection_test.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/odbc-test/src/configuration_test.cpp b/src/odbc-test/src/configuration_test.cpp index f4be22152..c943e24b8 100644 --- a/src/odbc-test/src/configuration_test.cpp +++ b/src/odbc-test/src/configuration_test.cpp @@ -554,7 +554,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringValidReadPreference) BOOST_AUTO_TEST_CASE(TestConnectStringInvalidBoolKeys) { - using Set = std::set>; + typedef std::set Set; Set keys; @@ -581,7 +581,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringInvalidBoolKeys) BOOST_AUTO_TEST_CASE(TestConnectStringValidBoolKeys) { - using Set = std::set>; + typedef std::set Set; Set keys; diff --git a/src/odbc-test/src/connection_test.cpp b/src/odbc-test/src/connection_test.cpp index 28714a040..211f1933b 100644 --- a/src/odbc-test/src/connection_test.cpp +++ b/src/odbc-test/src/connection_test.cpp @@ -96,7 +96,7 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite connectionString = "DRIVER={Apache Ignite};" - "ADDRESS=" + host + ":" + port + ";" + "HOSTNAME=" + host + ":" + port + ";" "SCHEMA=test;" "USER=" + user + ";" "PASSWORD=" + password + ";"; From 9e01a14ec4fb4d8ec669f24082e69933bc489636 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Mon, 24 Jan 2022 15:23:16 -0800 Subject: [PATCH 052/165] Change connection_test to use databse key instead of schema key --- src/odbc-test/src/connection_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/src/connection_test.cpp b/src/odbc-test/src/connection_test.cpp index 211f1933b..1c2dafbf3 100644 --- a/src/odbc-test/src/connection_test.cpp +++ b/src/odbc-test/src/connection_test.cpp @@ -97,7 +97,7 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite connectionString = "DRIVER={Apache Ignite};" "HOSTNAME=" + host + ":" + port + ";" - "SCHEMA=test;" + "DATABASE=test;" "USER=" + user + ";" "PASSWORD=" + password + ";"; } From cbaeedd0cde8b82bc29134efcad28dba943751c2 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 24 Jan 2022 16:09:55 -0800 Subject: [PATCH 053/165] [AD-522] implement read Preference * add SpaceToUnderscore function * implement read Preference in Config window and save the value --- src/common/include/ignite/common/utils.h | 10 ++++++ .../system/ui/dsn_configuration_window.cpp | 31 +++++++++++-------- src/odbc/os/win/src/system/ui/window.cpp | 14 +++++++++ src/odbc/src/read_preference.cpp | 2 ++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/common/include/ignite/common/utils.h b/src/common/include/ignite/common/utils.h index 9d17d655d..4a8369f1f 100644 --- a/src/common/include/ignite/common/utils.h +++ b/src/common/include/ignite/common/utils.h @@ -65,6 +65,16 @@ namespace ignite return res; } + /** + * Replaces whitespaces in string with underscores. + * + * @param str String to be transformed. + */ + inline void SpaceToUnderscore(std::string& str) + { + std::replace(str.begin(), str.end(), ' ', '_'); + } + /** * Strips leading and trailing whitespaces from string. * diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index e7c02c5d3..c35bde41a 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -70,7 +70,6 @@ namespace ignite appNameEdit(), readPreferenceLabel(), readPreferenceComboBox(), - //readPreferenceEdit(), replicaSetLabel(), replicaSetEdit(), retryReadsCheckBox(), @@ -553,7 +552,7 @@ namespace ignite // rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight // I believe - /*//TODO readPreference + //TODO readPreference ReadPreference::Type readPreference = config.GetReadPreference(); std::string readPreferenceStr = ReadPreference::ToString(readPreference); @@ -566,15 +565,18 @@ namespace ignite editPosX, rowPos, editSizeX, ROW_HEIGHT, "", ChildId::READ_PREFERENCE_COMBO_BOX); - readPreferenceComboBox->AddString("disable"); - sslModeComboBox->AddString("require"); + readPreferenceComboBox->AddString("Primary"); + readPreferenceComboBox->AddString("Primary Preferred"); + readPreferenceComboBox->AddString("Secondary"); + readPreferenceComboBox->AddString("Secondary Preferred"); + readPreferenceComboBox->AddString("Nearest"); - sslModeComboBox->SetSelection(sslMode); // set default + readPreferenceComboBox->SetSelection(readPreference); // set default rowPos += INTERVAL + ROW_HEIGHT; - */ + - const char* val = config.GetApplicationName().c_str(); + val = config.GetApplicationName().c_str(); appNameLabel = CreateLabel( labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Application Name:", ChildId::APP_NAME_LABEL); @@ -862,12 +864,12 @@ namespace ignite void DsnConfigurationWindow::RetrieveAdditionalParameters(config::Configuration& cfg) const { - std::string appNameStr; std::string readPreferenceStr; + std::string appNameStr; std::string replicaSetStr; + readPreferenceComboBox->GetText(readPreferenceStr); appNameEdit->GetText(appNameStr); - //readPreferenceEdit->GetText(readPreferenceStr); replicaSetEdit->GetText(replicaSetStr); bool retryReads = retryReadsCheckBox->IsChecked(); @@ -893,18 +895,21 @@ namespace ignite fetchSize = config.GetDefaultFetchSize(); LOG_MSG("Retrieving arguments:"); + LOG_MSG("Retry reads: " << (retryReads ? "true" : "false")); + LOG_MSG("Read preference: " << readPreferenceStr); LOG_MSG("App name: " << appNameStr); LOG_MSG("Login timeout (seconds): " << loginTimeoutSecStr); - LOG_MSG("Read preference: " << readPreferenceStr); LOG_MSG("Replica Set: " << replicaSetStr); - LOG_MSG("Retry reads: " << (retryReads ? "true" : "false")); LOG_MSG("Fetch size: " << fetchSize); + ReadPreference::Type readPreference = ReadPreference::FromString( + readPreferenceStr, ReadPreference::Type::PRIMARY); + + cfg.SetReadPreference(readPreference); + cfg.SetRetryReads(retryReads); cfg.SetApplicationName(appNameStr); cfg.SetLoginTimeoutSeconds(loginTimeoutSec); - //cfg.SetReadPreference(readPreferenceStr); cfg.SetReplicaSet(replicaSetStr); - cfg.SetRetryReads(retryReads); cfg.SetDefaultFetchSize(fetchSize); } diff --git a/src/odbc/os/win/src/system/ui/window.cpp b/src/odbc/os/win/src/system/ui/window.cpp index 8f2340a12..b4a64bd8b 100644 --- a/src/odbc/os/win/src/system/ui/window.cpp +++ b/src/odbc/os/win/src/system/ui/window.cpp @@ -159,6 +159,20 @@ namespace ignite SNDMSG(handle, WM_SETTEXT, 0, reinterpret_cast(text.c_str())); } + bool Window::HasText() const { + if (!IsEnabled()) { + return false; + } + + int len = GetWindowTextLength(handle); + + if (len <= 0) { + return false; + } + + return true; + } + bool Window::IsChecked() const { return IsEnabled() && Button_GetCheck(handle) == BST_CHECKED; diff --git a/src/odbc/src/read_preference.cpp b/src/odbc/src/read_preference.cpp index 43d81c4dc..0b0696e97 100644 --- a/src/odbc/src/read_preference.cpp +++ b/src/odbc/src/read_preference.cpp @@ -29,6 +29,8 @@ namespace ignite common::StripSurroundingWhitespaces(lowerVal); + common::SpaceToUnderscore(lowerVal); + if (lowerVal == "primary") return ReadPreference::Type::PRIMARY; From 2345c4104a1b5d89654f5fbb7bf03d84c5641b06 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Mon, 24 Jan 2022 16:17:35 -0800 Subject: [PATCH 054/165] Attempt to fix windows 32 build --- src/odbc/src/connection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index 643875737..b2a471529 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -639,7 +639,7 @@ namespace ignite std::string Connection::FormatJdbcConnectionString() const { std::string host = "localhost"; - uint16_t port = 27017; + std::string port = "27017"; std::string jdbConnectionString; if (config.IsHostnameSet()) { @@ -647,7 +647,7 @@ namespace ignite } if (config.IsPortSet()) { - port = config.GetPort(); + port = std::to_string(config.GetPort()); } jdbConnectionString = "jdbc:documentdb:"; From 3f6b3762b90b74f591b46f0dcdcdf909583c670a Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 24 Jan 2022 17:00:51 -0800 Subject: [PATCH 055/165] [AD-522] refactor dsn_configuration_window.cpp refactor code format; remove spaces and unnecessary comments --- .../os/win/src/system/ui/dsn_configuration_window.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index c35bde41a..cf36773c4 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -19,8 +19,7 @@ #include #include "ignite/odbc/log.h" -#include "ignite/odbc/read_preference.h" // causes build errors, comment out momentarily -// #include "ignite/odbc/ssl_mode.h" //TODO remove later +#include "ignite/odbc/read_preference.h" #include "ignite/odbc/system/ui/dsn_configuration_window.h" #include "ignite/odbc/config/config_tools.h" @@ -512,7 +511,8 @@ namespace ignite } */ - int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) { + int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) + { enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also // change it to the same @@ -879,7 +879,7 @@ namespace ignite loginTimeoutSecEdit->GetText(loginTimeoutSecStr); int32_t loginTimeoutSec = - common::LexicalCast< int32_t >(loginTimeoutSecStr); + common::LexicalCast(loginTimeoutSecStr); if (loginTimeoutSec <= 0) loginTimeoutSec = config.GetLoginTimeoutSeconds(); @@ -889,7 +889,7 @@ namespace ignite defaultFetchSizeEdit->GetText(fetchSizeStr); int32_t fetchSize = - common::LexicalCast< int32_t >(fetchSizeStr); + common::LexicalCast(fetchSizeStr); if (fetchSize <= 0) fetchSize = config.GetDefaultFetchSize(); From 13786309aa1cb5e1feccb54b50e7e6c4a0da574b Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 24 Jan 2022 17:02:46 -0800 Subject: [PATCH 056/165] [AD-522] fix config window margins now the config window is symmetric --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index cf36773c4..2259797b4 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -124,8 +124,10 @@ namespace ignite int groupPosYLeft = MARGIN; //int groupSizeY = width - 2 * MARGIN; // original int groupSizeY = width / 2 - 2 * MARGIN; - int posXRight = MARGIN + (width - MARGIN) / 2; + int posXRight = width / 2 + MARGIN; + //int posXRight = MARGIN + (width - MARGIN) / 2; //int posXRight = MARGIN + groupSizeY; + //int posXRight = 2 * MARGIN + groupSizeY; int groupPosYRight = MARGIN; // create left column group settings From a014cac5b180856e2fa302defd2cd9f834905df9 Mon Sep 17 00:00:00 2001 From: Andie Montoya Date: Mon, 24 Jan 2022 17:18:10 -0800 Subject: [PATCH 057/165] Fix formatting --- src/odbc/src/config/connection_string_parser.cpp | 2 +- src/odbc/src/connection.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index 8882792b2..e6857dcf1 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -408,7 +408,7 @@ namespace ignite if (diag) { diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Default fetch size attribute value is too large." + MakeErrorMessage("Scan limit size attribute value is too large." " Using default value.", key, value)); } diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index b2a471529..db1a0fec2 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -684,7 +684,7 @@ namespace ignite return jdbConnectionString; } - /** + /** * Create JVM options from configuration. * * @param cfg Configuration. From 4c49492cad9728ecd4003f7847f0e65228b6d9e2 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 09:16:49 -0800 Subject: [PATCH 058/165] [AD-522] add HasText() function to window.h * previously, the definition of HasText was mistakenly committed in commit cbaeedd0cde8b82bc29134efcad28dba943751c2. * add header of HasText() to resolve building errors in origin * update HasText() function to make code simpler --- .../win/include/ignite/odbc/system/ui/window.h | 7 +++++++ src/odbc/os/win/src/system/ui/window.cpp | 17 +++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/odbc/os/win/include/ignite/odbc/system/ui/window.h b/src/odbc/os/win/include/ignite/odbc/system/ui/window.h index 32a54b200..86681af9c 100644 --- a/src/odbc/os/win/include/ignite/odbc/system/ui/window.h +++ b/src/odbc/os/win/include/ignite/odbc/system/ui/window.h @@ -115,6 +115,13 @@ namespace ignite */ void SetText(const std::string& text) const; + /** + * Check if the window has text. + * + * @return True if has text. + */ + bool HasText() const; + /** * Get CheckBox state. * diff --git a/src/odbc/os/win/src/system/ui/window.cpp b/src/odbc/os/win/src/system/ui/window.cpp index b4a64bd8b..097dee836 100644 --- a/src/odbc/os/win/src/system/ui/window.cpp +++ b/src/odbc/os/win/src/system/ui/window.cpp @@ -160,17 +160,18 @@ namespace ignite } bool Window::HasText() const { - if (!IsEnabled()) { - return false; - } + return IsEnabled() && GetWindowTextLength(handle) > 0; + //if (!IsEnabled()) { + // return false; + //} - int len = GetWindowTextLength(handle); + //int len = GetWindowTextLength(handle); - if (len <= 0) { - return false; - } + //if (len <= 0) { + // return false; + //} - return true; + //return true; } bool Window::IsChecked() const From b0b731bd7416fab92084c87beebdff60c6c7514d Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 11:09:05 -0800 Subject: [PATCH 059/165] [AD-522] make "rs0" the default value of replicaSet --- src/odbc/src/config/configuration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 3d99ca6b9..43289d4ab 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -63,7 +63,7 @@ namespace ignite const std::string Configuration::DefaultValue::appName = "Amazon DocumentDB ODBC Driver"; const int32_t Configuration::DefaultValue::loginTimeoutSec = 0; const ReadPreference::Type Configuration::DefaultValue::readPreference = ReadPreference::Type::PRIMARY; - const std::string Configuration::DefaultValue::replicaSet = ""; + const std::string Configuration::DefaultValue::replicaSet = "rs0"; const bool Configuration::DefaultValue::retryReads = true; const int32_t Configuration::DefaultValue::defaultFetchSize = 2000; From b7d3b881f1c516fc362ef669f03c711030934647 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 11:14:14 -0800 Subject: [PATCH 060/165] [AD-522] implement database, hostname, port fields. And disable ok button unless all required fields are filled * implement database, hostname, port fields. * disable ok button unless all required fields (database, hostname, port, username, password) are filled * added boolean created to indicate whether the configuration window has been created. If has, then check for disabling/enabling the Ok button --- .../odbc/system/ui/dsn_configuration_window.h | 35 +++++++ .../system/ui/dsn_configuration_window.cpp | 99 ++++++++++++++++--- 2 files changed, 123 insertions(+), 11 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index f6e747eef..0bf963e57 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -87,6 +87,14 @@ namespace ignite TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, TLS_CA_FILE_EDIT, TLS_CA_FILE_LABEL, + DRIVER_LABEL, + DRIVER_EDIT, + DATABASE_LABEL, + DATABASE_EDIT, + HOST_NAME_LABEL, + HOST_NAME_EDIT, + PORT_LABEL, + PORT_EDIT, USER_LABEL, USER_EDIT, PASSWORD_LABEL, @@ -376,6 +384,30 @@ namespace ignite /** TLS certificate authority file edit. */ std::auto_ptr tlsCaFileEdit; + ///** Driver label. */ + //std::auto_ptr driverLabel; + + ///** Driver edit. */ + //std::auto_ptr driverEdit; + + /** Database label. */ + std::auto_ptr databaseLabel; + + /** Database edit. */ + std::auto_ptr databaseEdit; + + /** Hostname label. */ + std::auto_ptr hostnameLabel; + + /** Hostname edit. */ + std::auto_ptr hostnameEdit; + + /** Port label. */ + std::auto_ptr portLabel; + + /** Port edit. */ + std::auto_ptr portEdit; + /** User label. */ std::auto_ptr userLabel; @@ -393,6 +425,9 @@ namespace ignite /** Flag indicating whether OK option was selected. */ bool accepted; + + /** Flag indicating whether the configuration window has been created. */ + bool created; }; } } diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 2259797b4..bf37bc883 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -76,6 +76,14 @@ namespace ignite defaultFetchSizeEdit(), protocolVersionLabel(), protocolVersionComboBox(), + //driverLabel(), + //driverEdit(), + databaseLabel(), + databaseEdit(), + hostnameLabel(), + hostnameEdit(), + portLabel(), + portEdit(), userLabel(), userEdit(), passwordLabel(), @@ -83,7 +91,8 @@ namespace ignite okButton(), cancelButton(), config(config), - accepted(false) + accepted(false), + created(false) { // No-op. } @@ -149,6 +158,13 @@ namespace ignite cancelButton = CreateButton(cancelPosX, groupPosYRight, BUTTON_WIDTH, BUTTON_HEIGHT, "Cancel", ChildId::CANCEL_BUTTON); + // check whether the required fields are filled. If not, Ok button is disabled. + created = true; + okButton->SetEnabled( + userEdit->HasText() && passwordEdit->HasText() + && databaseEdit->HasText() && hostnameEdit->HasText() + && portEdit->HasText()); + // original code by Ignite //okButton = CreateButton(okPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, "Ok", ChildId::OK_BUTTON); //cancelButton = CreateButton(cancelPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, @@ -232,7 +248,35 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; - const char* val = config.GetUser().c_str(); + const char* val = config.GetHostname().c_str(); + hostnameLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Hostname :", ChildId::HOST_NAME_LABEL); + hostnameEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::HOST_NAME_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + std::string tmp = common::LexicalCast(config.GetTcpPort()); + val = tmp.c_str(); + portLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Port:", ChildId::PORT_LABEL); + portEdit = CreateEdit( + editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::PORT_EDIT, ES_NUMBER); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetDatabase().c_str(); + databaseLabel = + CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Database :", ChildId::DATABASE_LABEL); + databaseEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, ChildId::DATABASE_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetUser().c_str(); userLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "User :", ChildId::USER_LABEL); userEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::USER_EDIT); @@ -554,7 +598,6 @@ namespace ignite // rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight // I believe - //TODO readPreference ReadPreference::Type readPreference = config.GetReadPreference(); std::string readPreferenceStr = ReadPreference::ToString(readPreference); @@ -667,6 +710,25 @@ namespace ignite break; } + case ChildId::HOST_NAME_EDIT: + case ChildId::PORT_EDIT: + case ChildId::DATABASE_EDIT: + case ChildId::USER_EDIT: + case ChildId::PASSWORD_EDIT: + { + // if window has been created. Check + if (created) { + okButton->SetEnabled( + userEdit->HasText() + && passwordEdit->HasText() + && databaseEdit->HasText() + && hostnameEdit->HasText() + && portEdit->HasText()); + } + break; + } + + case ChildId::SSH_ENABLE_CHECK_BOX: { sshEnableCheckBox->SetChecked(!sshEnableCheckBox->IsChecked()); @@ -798,14 +860,29 @@ namespace ignite void DsnConfigurationWindow::RetrieveAuthParameters(config::Configuration& cfg) const { - std::string user; - std::string password; - - userEdit->GetText(user); - passwordEdit->GetText(password); - - cfg.SetUser(user); - cfg.SetPassword(password); + std::string hostnameStr; + std::string portStr; + std::string databaseStr; + std::string userStr; + std::string passwordStr; + + hostnameEdit->GetText(hostnameStr); + portEdit->GetText(portStr); + databaseEdit->GetText(databaseStr); + userEdit->GetText(userStr); + passwordEdit->GetText(passwordStr); + + int16_t port = + common::LexicalCast(portStr); + + if (port <= 0) + port = config.GetTcpPort(); + + cfg.SetTcpPort(port); + cfg.SetHostname(hostnameStr); + cfg.SetDatabase(databaseStr); + cfg.SetUser(userStr); + cfg.SetPassword(passwordStr); } void DsnConfigurationWindow::RetrieveSshParameters(config::Configuration& cfg) const From 78426888d6bbaa09e74984d2e8ef2a6d28ca9ea8 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 11:34:37 -0800 Subject: [PATCH 061/165] [AD-522] rename SSH Known Hosts File label for clarity --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index bf37bc883..ae945b509 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -349,7 +349,7 @@ namespace ignite val = config.GetSshKnownHostsFile().c_str(); sshKnownHostsFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSH Known Hosts:", ChildId::SSH_KNOWN_HOSTS_FILE_LABEL); + "SSH Known Hosts File:", ChildId::SSH_KNOWN_HOSTS_FILE_LABEL); sshKnownHostsFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_KNOWN_HOSTS_FILE_EDIT); From 95fda4cb484513094bd5dc2d88c1daa97152f39a Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 11:35:44 -0800 Subject: [PATCH 062/165] [AD-522] refactor logs for retrieving TSL settings Make the sentences align --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index ae945b509..d10a63976 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -930,9 +930,9 @@ namespace ignite tlsCaFileEdit->GetText(tlsCaStr); - LOG_MSG("TLS/SSL Encryption: " << (tls ? "true" : "false")); - LOG_MSG("tls Allow Invalid Hostnames: " << (tlsAllowInvalidHostnames ? "true" : "false")); - LOG_MSG("TLS CA (Certificate Authority): " << tlsCaStr); + LOG_MSG("TLS/SSL Encryption: " << (tls ? "true" : "false")); + LOG_MSG("tls Allow Invalid Hostnames: " << (tlsAllowInvalidHostnames ? "true" : "false")); + LOG_MSG("TLS CA (Certificate Authority) File name: " << tlsCaStr); cfg.SetTls(tls); cfg.SetTlsAllowInvalidHostnames(tlsAllowInvalidHostnames); From 0018921a3bc58eb259423299b1db7adce30139e7 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 11:41:03 -0800 Subject: [PATCH 063/165] [AD-522] rename TLS CA File label for clarity * change label length to the same label length as connection settings group --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index d10a63976..3c50fe2be 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -422,8 +422,8 @@ namespace ignite int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) { // TODO: rename function name from Ssl to TLS after UI works - - enum { LABEL_WIDTH = 120 }; + + enum { LABEL_WIDTH = 100 }; int labelPosX = posX + INTERVAL; @@ -449,7 +449,7 @@ namespace ignite const char* val = config.GetTlsCaFile().c_str(); tlsCaFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "TLS Certificate Authority:", ChildId::TLS_CA_FILE_LABEL); + "TLS CA File:", ChildId::TLS_CA_FILE_LABEL); tlsCaFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::TLS_CA_FILE_EDIT); From 982ac4ee97b67125439f24489b94141a413c9d73 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 11:47:44 -0800 Subject: [PATCH 064/165] [AD-522] move authorization setting fields to connection fields reason: only username and password are authorization settings, the rest are not. We chose to put username, password in the connections group because all fields in the connections group are required. --- .../odbc/system/ui/dsn_configuration_window.h | 10 +-- .../system/ui/dsn_configuration_window.cpp | 81 ++++++++++++++++++- 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 0bf963e57..41114e706 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -49,7 +49,7 @@ namespace ignite SSH_SETTINGS_GROUP_BOX, SSL_SETTINGS_GROUP_BOX, ADDITIONAL_SETTINGS_GROUP_BOX, - AUTH_SETTINGS_GROUP_BOX, + //AUTH_SETTINGS_GROUP_BOX, NAME_EDIT, NAME_LABEL, ADDRESS_EDIT, @@ -172,7 +172,7 @@ namespace ignite * * @param cfg Configuration. */ - void RetrieveAuthParameters(config::Configuration& cfg) const; + //void RetrieveAuthParameters(config::Configuration& cfg) const; /** * Retrieves current values from the SSH tunnel UI group and @@ -216,7 +216,7 @@ namespace ignite * @param sizeX Width. * @return Size by Y. */ - int CreateAuthSettingsGroup(int posX, int posY, int sizeX); + //int CreateAuthSettingsGroup(int posX, int posY, int sizeX); /** * Create internal SSH tunnel settings group box. @@ -263,8 +263,8 @@ namespace ignite /** SSL settings group box. */ std::auto_ptr sslSettingsGroupBox; - /** Authentication settings group box. */ - std::auto_ptr authSettingsGroupBox; + ///** Authentication settings group box. */ + //std::auto_ptr authSettingsGroupBox; /** Additional settings group box. */ std::auto_ptr additionalSettingsGroupBox; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 3c50fe2be..12ee1bd0d 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -43,7 +43,7 @@ namespace ignite connectionSettingsGroupBox(), sslSettingsGroupBox(), // has a create... function defined tlsCheckBox(), - authSettingsGroupBox(), + //authSettingsGroupBox(), additionalSettingsGroupBox(), nameLabel(), nameEdit(), @@ -141,8 +141,8 @@ namespace ignite // create left column group settings groupPosYLeft += INTERVAL + CreateConnectionSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); - groupPosYLeft += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); groupPosYLeft += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); + //groupPosYLeft += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); // create right column group settings groupPosYRight += INTERVAL + CreateSshSettingsGroup(posXRight, groupPosYRight, groupSizeY); groupPosYRight += INTERVAL + CreateAdditionalSettingsGroup(posXRight, groupPosYRight, groupSizeY); @@ -189,6 +189,49 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; + val = config.GetHostname().c_str(); + hostnameLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Hostname :", ChildId::HOST_NAME_LABEL); + hostnameEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::HOST_NAME_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + std::string tmp = common::LexicalCast(config.GetTcpPort()); + val = tmp.c_str(); + portLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Port:", ChildId::PORT_LABEL); + portEdit = CreateEdit( + editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::PORT_EDIT, ES_NUMBER); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetDatabase().c_str(); + databaseLabel = + CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Database :", ChildId::DATABASE_LABEL); + databaseEdit = CreateEdit(editPosX, rowPos, editSizeX, + ROW_HEIGHT, val, ChildId::DATABASE_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetUser().c_str(); + userLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "User :", ChildId::USER_LABEL); + userEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::USER_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetPassword().c_str(); + passwordLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Password:", ChildId::PASSWORD_LABEL); + passwordEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::USER_EDIT, ES_PASSWORD); + + rowPos += INTERVAL + ROW_HEIGHT; + + /* // original code for hostname std::string addr = config.GetHostname(); val = addr.c_str(); @@ -197,6 +240,7 @@ namespace ignite addressEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::ADDRESS_EDIT); rowPos += INTERVAL + ROW_HEIGHT; + */ val = config.GetDatabase().c_str(); schemaLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, @@ -237,6 +281,8 @@ namespace ignite return rowPos - posY; } + // comment out authSettingsGroup because they are no longer needed + /* int DsnConfigurationWindow::CreateAuthSettingsGroup(int posX, int posY, int sizeX) { enum { LABEL_WIDTH = 120 }; @@ -295,6 +341,7 @@ namespace ignite return rowPos - posY; } + */ int DsnConfigurationWindow::CreateSshSettingsGroup(int posX, int posY, int sizeX) { @@ -804,7 +851,7 @@ namespace ignite void DsnConfigurationWindow::RetrieveParameters(config::Configuration& cfg) const { RetrieveConnectionParameters(cfg); - RetrieveAuthParameters(cfg); + //RetrieveAuthParameters(cfg); RetrieveSshParameters(cfg); RetrieveSslParameters(cfg); RetrieveAdditionalParameters(cfg); @@ -817,6 +864,12 @@ namespace ignite std::string schemaStr; std::string versionStr; + std::string hostnameStr; + std::string portStr; + std::string databaseStr; + std::string userStr; + std::string passwordStr; + nameEdit->GetText(dsnStr); addressEdit->GetText(addressStr); schemaEdit->GetText(schemaStr); @@ -826,12 +879,25 @@ namespace ignite common::StripSurroundingWhitespaces(dsnStr); // Stripping of whitespaces off the schema skipped intentionally + hostnameEdit->GetText(hostnameStr); + portEdit->GetText(portStr); + databaseEdit->GetText(databaseStr); + userEdit->GetText(userStr); + passwordEdit->GetText(passwordStr); + + int16_t port = common::LexicalCast< int16_t >(portStr); + + if (port <= 0) + port = config.GetTcpPort(); + LOG_MSG("Retrieving arguments:"); LOG_MSG("DSN: " << dsnStr); LOG_MSG("Address: " << addressStr); LOG_MSG("Schema: " << schemaStr); LOG_MSG("Protocol version: " << versionStr); + // username and password intentionally not logged for security reasons + if (dsnStr.empty()) throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "DSN name can not be empty."); @@ -856,8 +922,16 @@ namespace ignite //cfg.SetAddresses(addresses); cfg.SetDatabase(schemaStr); //cfg.SetProtocolVersion(version); + + cfg.SetTcpPort(port); + cfg.SetHostname(hostnameStr); + cfg.SetDatabase(databaseStr); + cfg.SetUser(userStr); + cfg.SetPassword(passwordStr); } + // comment out because no longer needed + /* void DsnConfigurationWindow::RetrieveAuthParameters(config::Configuration& cfg) const { std::string hostnameStr; @@ -884,6 +958,7 @@ namespace ignite cfg.SetUser(userStr); cfg.SetPassword(passwordStr); } + */ void DsnConfigurationWindow::RetrieveSshParameters(config::Configuration& cfg) const { From a4d2e0d817fea0b9c910a986ecccb6a737aa7390 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 12:46:05 -0800 Subject: [PATCH 065/165] [AD-522] bugfix-comment out address field related code in RetrieveConnectionParameters --- .../os/win/src/system/ui/dsn_configuration_window.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 12ee1bd0d..73e90c250 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -860,7 +860,7 @@ namespace ignite void DsnConfigurationWindow::RetrieveConnectionParameters(config::Configuration& cfg) const { std::string dsnStr; - std::string addressStr; + //std::string addressStr; std::string schemaStr; std::string versionStr; @@ -871,11 +871,11 @@ namespace ignite std::string passwordStr; nameEdit->GetText(dsnStr); - addressEdit->GetText(addressStr); + //addressEdit->GetText(addressStr); schemaEdit->GetText(schemaStr); protocolVersionComboBox->GetText(versionStr); - common::StripSurroundingWhitespaces(addressStr); + //common::StripSurroundingWhitespaces(addressStr); common::StripSurroundingWhitespaces(dsnStr); // Stripping of whitespaces off the schema skipped intentionally @@ -892,7 +892,7 @@ namespace ignite LOG_MSG("Retrieving arguments:"); LOG_MSG("DSN: " << dsnStr); - LOG_MSG("Address: " << addressStr); + //LOG_MSG("Address: " << addressStr); LOG_MSG("Schema: " << schemaStr); LOG_MSG("Protocol version: " << versionStr); @@ -905,7 +905,7 @@ namespace ignite std::vector addresses; - config::ParseAddress(addressStr, addresses, &diag); + //config::ParseAddress(addressStr, addresses, &diag); if (diag.GetStatusRecordsNumber() > 0) { From 260e6629fd727cac54224c8d535b4abc1e2195c3 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 12:53:29 -0800 Subject: [PATCH 066/165] [AD-522] rename sslSettings to tlsSettings and add comment for connection settings group --- .../ignite/odbc/system/ui/dsn_configuration_window.h | 8 ++++---- .../win/src/system/ui/dsn_configuration_window.cpp | 12 ++++++------ src/odbc/src/config/configuration.cpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 41114e706..9b7329a36 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -188,7 +188,7 @@ namespace ignite * * @param cfg Configuration. */ - void RetrieveSslParameters(config::Configuration& cfg) const; + void RetrieveTlsParameters(config::Configuration& cfg) const; /** * Retrieves current values from the additional UI group and @@ -236,7 +236,7 @@ namespace ignite * @param sizeX Width. * @return Size by Y. */ - int CreateSslSettingsGroup(int posX, int posY, int sizeX); + int CreateTlsSettingsGroup(int posX, int posY, int sizeX); /** * Create additional settings group box. @@ -260,8 +260,8 @@ namespace ignite /** SSH settings group box. */ std::auto_ptr sshSettingsGroupBox; - /** SSL settings group box. */ - std::auto_ptr sslSettingsGroupBox; + /** TLS settings group box. */ + std::auto_ptr tlsSettingsGroupBox; ///** Authentication settings group box. */ //std::auto_ptr authSettingsGroupBox; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 73e90c250..182effad8 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -41,7 +41,7 @@ namespace ignite //width(360), //height(800), connectionSettingsGroupBox(), - sslSettingsGroupBox(), // has a create... function defined + tlsSettingsGroupBox(), // has a create... function defined tlsCheckBox(), //authSettingsGroupBox(), additionalSettingsGroupBox(), @@ -141,8 +141,8 @@ namespace ignite // create left column group settings groupPosYLeft += INTERVAL + CreateConnectionSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); - groupPosYLeft += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); //groupPosYLeft += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); + groupPosYLeft += INTERVAL + CreateTlsSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); // create right column group settings groupPosYRight += INTERVAL + CreateSshSettingsGroup(posXRight, groupPosYRight, groupSizeY); groupPosYRight += INTERVAL + CreateAdditionalSettingsGroup(posXRight, groupPosYRight, groupSizeY); @@ -467,7 +467,7 @@ namespace ignite } */ - int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) + int DsnConfigurationWindow::CreateTlsSettingsGroup(int posX, int posY, int sizeX) { // TODO: rename function name from Ssl to TLS after UI works enum { LABEL_WIDTH = 100 }; @@ -502,7 +502,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + tlsSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "TLS/SSL Settings", ChildId::SSL_SETTINGS_GROUP_BOX); tlsAllowInvalidHostnamesCheckBox->SetEnabled(tlsCheckBox->IsChecked()); @@ -853,7 +853,7 @@ namespace ignite RetrieveConnectionParameters(cfg); //RetrieveAuthParameters(cfg); RetrieveSshParameters(cfg); - RetrieveSslParameters(cfg); + RetrieveTlsParameters(cfg); RetrieveAdditionalParameters(cfg); } @@ -996,7 +996,7 @@ namespace ignite } - void DsnConfigurationWindow::RetrieveSslParameters(config::Configuration& cfg) const + void DsnConfigurationWindow::RetrieveTlsParameters(config::Configuration& cfg) const { bool tls = tlsCheckBox->IsChecked(); diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 43289d4ab..bc85adb80 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -30,7 +30,7 @@ namespace ignite { namespace config { - + // Connection Settings const std::string Configuration::DefaultValue::dsn = "DocumentDB DSN"; const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB ODBC Driver"; const std::string Configuration::DefaultValue::database = ""; From 0063e20dfbae4b2ee989ea17cbcd8a9c559f7491 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 13:20:41 -0800 Subject: [PATCH 067/165] [AD-522] remove protocol version from config window --- .../odbc/system/ui/dsn_configuration_window.h | 18 +++---- .../system/ui/dsn_configuration_window.cpp | 50 +++++++++---------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 9b7329a36..7414e3a71 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -22,7 +22,7 @@ #include "ignite/odbc/system/ui/custom_window.h" // TODO: Removed these from configuration.h since no longer used. Moved here since they are still referenced. Remove when no longer needed. #include "ignite/odbc/nested_tx_mode.h" -#include "ignite/odbc/protocol_version.h" +//#include "ignite/odbc/protocol_version.h" #include "ignite/odbc/ssl_mode.h" namespace ignite @@ -52,8 +52,8 @@ namespace ignite //AUTH_SETTINGS_GROUP_BOX, NAME_EDIT, NAME_LABEL, - ADDRESS_EDIT, - ADDRESS_LABEL, + //ADDRESS_EDIT, + //ADDRESS_LABEL, SCHEMA_EDIT, SCHEMA_LABEL, SSH_ENABLE_CHECK_BOX, @@ -79,8 +79,8 @@ namespace ignite RETRY_READS_CHECK_BOX, DEFAULT_FETCH_SIZE_EDIT, DEFAULT_FETCH_SIZE_LABEL, - PROTOCOL_VERSION_LABEL, - PROTOCOL_VERSION_COMBO_BOX, + //PROTOCOL_VERSION_LABEL, + //PROTOCOL_VERSION_COMBO_BOX, //NESTED_TX_MODE_LABEL, //NESTED_TX_MODE_COMBO_BOX, TLS_CHECK_BOX, @@ -360,11 +360,11 @@ namespace ignite /** Default fetch size label. */ std::auto_ptr defaultFetchSizeLabel; - /** Protocol version edit field. */ - std::auto_ptr protocolVersionLabel; + ///** Protocol version edit field. */ + //std::auto_ptr protocolVersionLabel; - /** Protocol verion ComboBox. */ - std::auto_ptr protocolVersionComboBox; + ///** Protocol verion ComboBox. */ + //std::auto_ptr protocolVersionComboBox; /** Ok button. */ std::auto_ptr okButton; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 182effad8..519d04347 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -74,8 +74,8 @@ namespace ignite retryReadsCheckBox(), defaultFetchSizeLabel(), defaultFetchSizeEdit(), - protocolVersionLabel(), - protocolVersionComboBox(), + //protocolVersionLabel(), + //protocolVersionComboBox(), //driverLabel(), //driverEdit(), databaseLabel(), @@ -249,31 +249,31 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - protocolVersionLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Protocol Version:", ChildId::PROTOCOL_VERSION_LABEL); - protocolVersionComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, - "Protocol Version", ChildId::PROTOCOL_VERSION_COMBO_BOX); + //protocolVersionLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + // "Protocol Version:", ChildId::PROTOCOL_VERSION_LABEL); + //protocolVersionComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, + // "Protocol Version", ChildId::PROTOCOL_VERSION_COMBO_BOX); - int id = 0; + //int id = 0; - const ProtocolVersion::VersionSet& supported = ProtocolVersion::GetSupported(); + //const ProtocolVersion::VersionSet& supported = ProtocolVersion::GetSupported(); - ProtocolVersion version = ProtocolVersion::GetCurrent(); + //ProtocolVersion version = ProtocolVersion::GetCurrent(); - if (!version.IsSupported()) - version = ProtocolVersion::GetCurrent(); + //if (!version.IsSupported()) + // version = ProtocolVersion::GetCurrent(); - for (ProtocolVersion::VersionSet::const_iterator it = supported.begin(); it != supported.end(); ++it) - { - protocolVersionComboBox->AddString(it->ToString()); + //for (ProtocolVersion::VersionSet::const_iterator it = supported.begin(); it != supported.end(); ++it) + //{ + // protocolVersionComboBox->AddString(it->ToString()); - if (*it == version) - protocolVersionComboBox->SetSelection(id); + // if (*it == version) + // protocolVersionComboBox->SetSelection(id); - ++id; - } + // ++id; + //} - rowPos += INTERVAL + ROW_HEIGHT; + //rowPos += INTERVAL + ROW_HEIGHT; connectionSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "Connection Settings", ChildId::CONNECTION_SETTINGS_GROUP_BOX); @@ -862,7 +862,7 @@ namespace ignite std::string dsnStr; //std::string addressStr; std::string schemaStr; - std::string versionStr; + //std::string versionStr; std::string hostnameStr; std::string portStr; @@ -873,7 +873,7 @@ namespace ignite nameEdit->GetText(dsnStr); //addressEdit->GetText(addressStr); schemaEdit->GetText(schemaStr); - protocolVersionComboBox->GetText(versionStr); + //protocolVersionComboBox->GetText(versionStr); //common::StripSurroundingWhitespaces(addressStr); common::StripSurroundingWhitespaces(dsnStr); @@ -894,7 +894,7 @@ namespace ignite LOG_MSG("DSN: " << dsnStr); //LOG_MSG("Address: " << addressStr); LOG_MSG("Schema: " << schemaStr); - LOG_MSG("Protocol version: " << versionStr); + //LOG_MSG("Protocol version: " << versionStr); // username and password intentionally not logged for security reasons @@ -913,10 +913,10 @@ namespace ignite diag.GetStatusRecord(1).GetMessageText().c_str()); } - ProtocolVersion version = ProtocolVersion::FromString(versionStr); + //ProtocolVersion version = ProtocolVersion::FromString(versionStr); - if (!version.IsSupported()) - throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "Protocol version is not supported."); + /*if (!version.IsSupported()) + throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "Protocol version is not supported.");*/ cfg.SetDsn(dsnStr); //cfg.SetAddresses(addresses); From bd62805102278c81fd3dd40d9410034638d04a02 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 13:50:42 -0800 Subject: [PATCH 068/165] [AD-522] bug fix sshKnownHostsFile not saved when Ok button is pressed --- src/odbc/src/dsn_config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index 3126580b3..da7c8cabe 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -204,8 +204,8 @@ namespace ignite SettableValue sshKnownHostsFile = ReadDsnString(dsn, ConnectionStringParser::Key::sshKnownHostsFile); - if (sshKnownHostsFile.IsSet() && !config.IsSshStrictHostKeyCheckingSet()) - config.SetSshStrictHostKeyChecking(sshStrictHostKeyChecking.GetValue()); + if (sshKnownHostsFile.IsSet() && !config.IsSshKnownHostsFileSet()) + config.SetSshKnownHostsFile(sshKnownHostsFile.GetValue()); SettableValue scanMethod = ReadDsnString(dsn, ConnectionStringParser::Key::scanMethod); From bddf4b54b8c41e88eb876ad33ac13146b513e07c Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 13:51:19 -0800 Subject: [PATCH 069/165] [AD-522] remove commented out #include headers --- src/odbc/src/config/connection_string_parser.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index d63a252f6..335de7b6a 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -20,10 +20,8 @@ #include "ignite/common/utils.h" #include "ignite/odbc/utility.h" -//#include "ignite/odbc/ssl_mode.h" #include "ignite/odbc/config/connection_string_parser.h" #include "ignite/odbc/config/config_tools.h" -//#include "ignite/odbc/nested_tx_mode.h" namespace ignite { From 8a3e732c579e20979ab443712c2696d14711d3fc Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 13:57:33 -0800 Subject: [PATCH 070/165] [AD-522] disable SSH Known Hosts File edit when SSH Strict Host Key Check check box is unchecked * move SSH Strict Host Key Checking check box above SSH Known Hosts File edit in the config window --- .../system/ui/dsn_configuration_window.cpp | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 519d04347..e49692f3e 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -394,18 +394,19 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT * 2; + // SSH Strict Host Key Check check box needs to have editSizeX as size because the string is long + sshStrictHostKeyCheckingCheckBox = CreateCheckBox( + labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "SSH Strict Host Key Check (disabling option is less secure)", + ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX, config.IsSshStrictHostKeyChecking()); + + rowPos += INTERVAL + ROW_HEIGHT; + val = config.GetSshKnownHostsFile().c_str(); sshKnownHostsFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSH Known Hosts File:", ChildId::SSH_KNOWN_HOSTS_FILE_LABEL); sshKnownHostsFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_KNOWN_HOSTS_FILE_EDIT); - rowPos += INTERVAL + ROW_HEIGHT; - // SSH Strict Host Key Check check box needs to have editSizeX as size because the string is long - sshStrictHostKeyCheckingCheckBox = CreateCheckBox( - labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, "SSH Strict Host Key Check (disabling option is less secure)", - ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX, config.IsSshStrictHostKeyChecking()); - rowPos += INTERVAL + ROW_HEIGHT; sshSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, @@ -416,8 +417,10 @@ namespace ignite sshHostEdit->SetEnabled(sshEnableCheckBox->IsChecked()); sshPrivateKeyFileEdit->SetEnabled( sshEnableCheckBox->IsChecked()); sshPrivateKeyPassphraseEdit->SetEnabled(sshEnableCheckBox->IsChecked()); - sshKnownHostsFileEdit->SetEnabled(sshEnableCheckBox->IsChecked()); sshStrictHostKeyCheckingCheckBox->SetEnabled(sshEnableCheckBox->IsChecked()); + sshKnownHostsFileEdit->SetEnabled( + sshEnableCheckBox->IsChecked() + && sshStrictHostKeyCheckingCheckBox->IsChecked()); return rowPos - posY; } @@ -790,7 +793,8 @@ namespace ignite ->SetEnabled( sshEnableCheckBox->IsChecked()); sshKnownHostsFileEdit->SetEnabled( - sshEnableCheckBox->IsChecked()); + sshEnableCheckBox->IsChecked() + && sshStrictHostKeyCheckingCheckBox->IsChecked()); break; } @@ -799,6 +803,9 @@ namespace ignite { sshStrictHostKeyCheckingCheckBox ->SetChecked(!sshStrictHostKeyCheckingCheckBox->IsChecked()); + sshKnownHostsFileEdit->SetEnabled( + sshEnableCheckBox->IsChecked() + && sshStrictHostKeyCheckingCheckBox->IsChecked()); break; } @@ -983,16 +990,16 @@ namespace ignite LOG_MSG("SSH host: " << sshHostStr); LOG_MSG("SSH private key file: " << sshPrivateKeyFileStr); LOG_MSG("SSH private key passphrase: " << sshPrivateKeyPassphraseStr); - LOG_MSG("SSH known hosts file: " << sshKnownHostsFileStr); LOG_MSG("SSH strict host key checking: " << (sshStrictHostKeyChecking ? "true" : "false")); + LOG_MSG("SSH known hosts file: " << sshKnownHostsFileStr); cfg.SetSshEnable(sshEnable); cfg.SetSshUser(sshUserStr); cfg.SetSshHost(sshHostStr); cfg.SetSshPrivateKeyFile(sshPrivateKeyFileStr); cfg.SetSshPrivateKeyPassphrase(sshPrivateKeyPassphraseStr); - cfg.SetSshKnownHostsFile(sshKnownHostsFileStr); cfg.SetSshStrictHostKeyChecking(sshStrictHostKeyChecking); + cfg.SetSshKnownHostsFile(sshKnownHostsFileStr); } From 57cceddddfa55942b7a093e90a8ec3c483d9a3b6 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 13:57:59 -0800 Subject: [PATCH 071/165] [AD-522] refactor - remove commented out header code --- .../include/ignite/odbc/system/ui/dsn_configuration_window.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 7414e3a71..824d0f769 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -21,9 +21,9 @@ #include "ignite/odbc/config/configuration.h" #include "ignite/odbc/system/ui/custom_window.h" // TODO: Removed these from configuration.h since no longer used. Moved here since they are still referenced. Remove when no longer needed. -#include "ignite/odbc/nested_tx_mode.h" +//#include "ignite/odbc/nested_tx_mode.h" //#include "ignite/odbc/protocol_version.h" -#include "ignite/odbc/ssl_mode.h" +//#include "ignite/odbc/ssl_mode.h" namespace ignite { From efe493a63321684fcdc2d27dec3e29e9e46c290b Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 14:29:14 -0800 Subject: [PATCH 072/165] [AD-522] add comments in configuration.cpp for planning * modify commented out example code in dsn_configuration_window.cpp for clarity --- .../os/win/src/system/ui/dsn_configuration_window.cpp | 4 ++-- src/odbc/src/config/configuration.cpp | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index e49692f3e..7a2d21af8 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -629,8 +629,8 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; // useful draft code for changing read preference into a - // mode (check JDBC page for available options) const char* - // val = sslModeStr.c_str(); + // mode (check JDBC page for available options) + // const char* val = sslModeStr.c_str(); // sslModeLabel = CreateLabel(labelPosX, rowPos, // LABEL_WIDTH, ROW_HEIGHT, diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index bc85adb80..314e67af1 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -32,10 +32,11 @@ namespace ignite { // Connection Settings const std::string Configuration::DefaultValue::dsn = "DocumentDB DSN"; - const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB ODBC Driver"; - const std::string Configuration::DefaultValue::database = ""; - const std::string Configuration::DefaultValue::hostname = ""; - const uint16_t Configuration::DefaultValue::port = 27017; + const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB ODBC Driver"; // -AL- add (= need to add to UI) + // driver does not need to be added in config window since it is chosen at the Data Source Administrator + const std::string Configuration::DefaultValue::database = ""; // -AL- add + const std::string Configuration::DefaultValue::hostname = ""; // -AL- add + const uint16_t Configuration::DefaultValue::port = 27017; // -AL- add const std::string Configuration::DefaultValue::user = ""; const std::string Configuration::DefaultValue::password = ""; From 0d04801e1a69192d7a9cdd63cc3b7b9600454395 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 14:30:22 -0800 Subject: [PATCH 073/165] [AD-522] change from SSL to TLS for consistency * SSL_SETTINGS_GROUP_BOX is changed to TLS_SETTINGS_GROUP_BOX --- .../ignite/odbc/system/ui/dsn_configuration_window.h | 6 +++--- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 824d0f769..094d69270 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -47,7 +47,7 @@ namespace ignite { CONNECTION_SETTINGS_GROUP_BOX = 100, SSH_SETTINGS_GROUP_BOX, - SSL_SETTINGS_GROUP_BOX, + TLS_SETTINGS_GROUP_BOX, ADDITIONAL_SETTINGS_GROUP_BOX, //AUTH_SETTINGS_GROUP_BOX, NAME_EDIT, @@ -183,7 +183,7 @@ namespace ignite void RetrieveSshParameters(config::Configuration& cfg) const; /** - * Retrieves current values from the SSL UI group and + * Retrieves current values from the TLS/SSL UI group and * stores them to the specified configuration. * * @param cfg Configuration. @@ -229,7 +229,7 @@ namespace ignite int CreateSshSettingsGroup(int posX, int posY, int sizeX); /** - * Create SSL settings group box. + * Create TLS/SSL settings group box. * * @param posX X position. * @param posY Y position. diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 7a2d21af8..ca4b91b91 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -506,7 +506,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; tlsSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "TLS/SSL Settings", ChildId::SSL_SETTINGS_GROUP_BOX); + "TLS/SSL Settings", ChildId::TLS_SETTINGS_GROUP_BOX); tlsAllowInvalidHostnamesCheckBox->SetEnabled(tlsCheckBox->IsChecked()); tlsCaFileEdit->SetEnabled(tlsCheckBox->IsChecked()); From 2fcfd6d6836bd9ebf4f2a2220751cd5bc70de03f Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 14:38:53 -0800 Subject: [PATCH 074/165] [AD-522] remove commented out code Removed commented out code: * RetrieveAuthParameters * CreateAuthSettingsGroup * CreateAdditionalSettingsGroup function and CreateSslSettingsGroup function for 1 column window * protocol version - related code * authSettingsGroupBox code --- .../odbc/system/ui/dsn_configuration_window.h | 45 --- .../system/ui/dsn_configuration_window.cpp | 293 ------------------ 2 files changed, 338 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 094d69270..dbca6bd5a 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -20,10 +20,6 @@ #include "ignite/odbc/config/configuration.h" #include "ignite/odbc/system/ui/custom_window.h" -// TODO: Removed these from configuration.h since no longer used. Moved here since they are still referenced. Remove when no longer needed. -//#include "ignite/odbc/nested_tx_mode.h" -//#include "ignite/odbc/protocol_version.h" -//#include "ignite/odbc/ssl_mode.h" namespace ignite { @@ -49,11 +45,8 @@ namespace ignite SSH_SETTINGS_GROUP_BOX, TLS_SETTINGS_GROUP_BOX, ADDITIONAL_SETTINGS_GROUP_BOX, - //AUTH_SETTINGS_GROUP_BOX, NAME_EDIT, NAME_LABEL, - //ADDRESS_EDIT, - //ADDRESS_LABEL, SCHEMA_EDIT, SCHEMA_LABEL, SSH_ENABLE_CHECK_BOX, @@ -79,10 +72,6 @@ namespace ignite RETRY_READS_CHECK_BOX, DEFAULT_FETCH_SIZE_EDIT, DEFAULT_FETCH_SIZE_LABEL, - //PROTOCOL_VERSION_LABEL, - //PROTOCOL_VERSION_COMBO_BOX, - //NESTED_TX_MODE_LABEL, - //NESTED_TX_MODE_COMBO_BOX, TLS_CHECK_BOX, TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, TLS_CA_FILE_EDIT, @@ -166,14 +155,6 @@ namespace ignite */ void RetrieveConnectionParameters(config::Configuration& cfg) const; - /** - * Retrieves current values from the Authentication UI group and - * stores them to the specified configuration. - * - * @param cfg Configuration. - */ - //void RetrieveAuthParameters(config::Configuration& cfg) const; - /** * Retrieves current values from the SSH tunnel UI group and * stores them to the specified configuration. @@ -208,16 +189,6 @@ namespace ignite */ int CreateConnectionSettingsGroup(int posX, int posY, int sizeX); - /** - * Create authentication settings group box. - * - * @param posX X position. - * @param posY Y position. - * @param sizeX Width. - * @return Size by Y. - */ - //int CreateAuthSettingsGroup(int posX, int posY, int sizeX); - /** * Create internal SSH tunnel settings group box. * @@ -338,10 +309,6 @@ namespace ignite /** Nested Read Preference ComboBox **/ std::auto_ptr readPreferenceComboBox; - // -AL- remove later - ///** Read preference edit. */ - //std::auto_ptr readPreferenceEdit; - /** Read preference label. */ std::auto_ptr readPreferenceLabel; @@ -360,12 +327,6 @@ namespace ignite /** Default fetch size label. */ std::auto_ptr defaultFetchSizeLabel; - ///** Protocol version edit field. */ - //std::auto_ptr protocolVersionLabel; - - ///** Protocol verion ComboBox. */ - //std::auto_ptr protocolVersionComboBox; - /** Ok button. */ std::auto_ptr okButton; @@ -384,12 +345,6 @@ namespace ignite /** TLS certificate authority file edit. */ std::auto_ptr tlsCaFileEdit; - ///** Driver label. */ - //std::auto_ptr driverLabel; - - ///** Driver edit. */ - //std::auto_ptr driverEdit; - /** Database label. */ std::auto_ptr databaseLabel; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index ca4b91b91..aa2e950cd 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -43,7 +43,6 @@ namespace ignite connectionSettingsGroupBox(), tlsSettingsGroupBox(), // has a create... function defined tlsCheckBox(), - //authSettingsGroupBox(), additionalSettingsGroupBox(), nameLabel(), nameEdit(), @@ -74,10 +73,6 @@ namespace ignite retryReadsCheckBox(), defaultFetchSizeLabel(), defaultFetchSizeEdit(), - //protocolVersionLabel(), - //protocolVersionComboBox(), - //driverLabel(), - //driverEdit(), databaseLabel(), databaseEdit(), hostnameLabel(), @@ -231,17 +226,6 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - /* // original code for hostname - std::string addr = config.GetHostname(); - - val = addr.c_str(); - addressLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Address:", ChildId::ADDRESS_LABEL); - addressEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::ADDRESS_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - */ - val = config.GetDatabase().c_str(); schemaLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Schema Name:", ChildId::SCHEMA_LABEL); @@ -249,100 +233,12 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - //protocolVersionLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - // "Protocol Version:", ChildId::PROTOCOL_VERSION_LABEL); - //protocolVersionComboBox = CreateComboBox(editPosX, rowPos, editSizeX, ROW_HEIGHT, - // "Protocol Version", ChildId::PROTOCOL_VERSION_COMBO_BOX); - - //int id = 0; - - //const ProtocolVersion::VersionSet& supported = ProtocolVersion::GetSupported(); - - //ProtocolVersion version = ProtocolVersion::GetCurrent(); - - //if (!version.IsSupported()) - // version = ProtocolVersion::GetCurrent(); - - //for (ProtocolVersion::VersionSet::const_iterator it = supported.begin(); it != supported.end(); ++it) - //{ - // protocolVersionComboBox->AddString(it->ToString()); - - // if (*it == version) - // protocolVersionComboBox->SetSelection(id); - - // ++id; - //} - - //rowPos += INTERVAL + ROW_HEIGHT; - connectionSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "Connection Settings", ChildId::CONNECTION_SETTINGS_GROUP_BOX); return rowPos - posY; } - // comment out authSettingsGroup because they are no longer needed - /* - int DsnConfigurationWindow::CreateAuthSettingsGroup(int posX, int posY, int sizeX) - { - enum { LABEL_WIDTH = 120 }; - - int labelPosX = posX + INTERVAL; - - int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; - int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; - - int rowPos = posY + 2 * INTERVAL; - - const char* val = config.GetHostname().c_str(); - hostnameLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Hostname :", ChildId::HOST_NAME_LABEL); - hostnameEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, - val, ChildId::HOST_NAME_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - - std::string tmp = common::LexicalCast(config.GetTcpPort()); - val = tmp.c_str(); - portLabel = CreateLabel( - labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Port:", ChildId::PORT_LABEL); - portEdit = CreateEdit( - editPosX, rowPos, editSizeX, ROW_HEIGHT, - val, ChildId::PORT_EDIT, ES_NUMBER); - - rowPos += INTERVAL + ROW_HEIGHT; - - val = config.GetDatabase().c_str(); - databaseLabel = - CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Database :", ChildId::DATABASE_LABEL); - databaseEdit = CreateEdit(editPosX, rowPos, editSizeX, - ROW_HEIGHT, val, ChildId::DATABASE_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - - val = config.GetUser().c_str(); - userLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "User :", ChildId::USER_LABEL); - userEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::USER_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - - val = config.GetPassword().c_str(); - passwordLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Password:", ChildId::PASSWORD_LABEL); - passwordEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, - val, ChildId::USER_EDIT, ES_PASSWORD); - - rowPos += INTERVAL + ROW_HEIGHT; - - authSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "Authentication Settings", ChildId::AUTH_SETTINGS_GROUP_BOX); - - return rowPos - posY; - } - */ - int DsnConfigurationWindow::CreateSshSettingsGroup(int posX, int posY, int sizeX) { enum { LABEL_WIDTH = 120 }; // -AL- copied from above function @@ -425,51 +321,6 @@ namespace ignite return rowPos - posY; } - // old SSL settings group code for 1 column config window - /* - int DsnConfigurationWindow::CreateSslSettingsGroup(int posX, int posY, int sizeX) - { // TODO: rename function name from Ssl to TLS after UI works - - enum { LABEL_WIDTH = 120 }; - - int labelPosX = posX + INTERVAL; - - int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; - int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; - - int rowPos = posY + 2 * INTERVAL; - - int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; - - tlsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "TLS", ChildId::TLS_CHECK_BOX, config.IsTls()); - - tlsAllowInvalidHostnamesCheckBox = CreateCheckBox( - labelPosX + checkBoxSize + INTERVAL, rowPos, - checkBoxSize, ROW_HEIGHT, "TLS Allow Invalid Hostnames", - ChildId::TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, - config.IsTlsAllowInvalidHostnames()); - - rowPos += INTERVAL + ROW_HEIGHT; - - const char* val = config.GetTlsCaFile().c_str(); - tlsCaFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "TLS Certificate Authority:", ChildId::TLS_CA_FILE_LABEL); - tlsCaFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, - ChildId::TLS_CA_FILE_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - - sslSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "TLS/SSL settings", ChildId::SSL_SETTINGS_GROUP_BOX); - - tlsCheckBox->SetEnabled(tlsCheckBox->IsChecked()); - tlsCaFileEdit->SetEnabled(tlsCheckBox->IsChecked()); - - return rowPos - posY; - } - */ - int DsnConfigurationWindow::CreateTlsSettingsGroup(int posX, int posY, int sizeX) { // TODO: rename function name from Ssl to TLS after UI works @@ -514,99 +365,6 @@ namespace ignite return rowPos - posY; } - // old additional settings group code for 1 column window - /* - int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) - { - enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also change it to the same - - int labelPosX = posX + INTERVAL; - - int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; - int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; - - int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; - - int rowPos = posY + 2 * INTERVAL; - - const char* val = config.GetApplicationName().c_str(); - - appNameLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, - ROW_HEIGHT, "Application Name:", ChildId::APP_NAME_LABEL); - appNameEdit = CreateEdit(editPosX, rowPos, editSizeX, - ROW_HEIGHT, val, ChildId::APP_NAME_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - - std::string tmp = common::LexicalCast< std::string >(config.GetLoginTimeoutSeconds()); - val = tmp.c_str(); - loginTimeoutSecLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, - ROW_HEIGHT, "Login Timeout (s):", ChildId::LOGIN_TIMEOUT_SEC_LABEL); - - loginTimeoutSecEdit = CreateEdit(editPosX, rowPos, editSizeX, - ROW_HEIGHT, val, ChildId::LOGIN_TIMEOUT_SEC_EDIT, ES_NUMBER); - - rowPos += INTERVAL + ROW_HEIGHT; - - // useful draft code for changing read preference into a mode (check JDBC page for available options) - // const char* val = sslModeStr.c_str(); - - // sslModeLabel = CreateLabel(labelPosX, rowPos, - // LABEL_WIDTH, ROW_HEIGHT, - // "SSL Mode:", ChildId::SSL_MODE_LABEL); - // sslModeComboBox = CreateComboBox(editPosX, rowPos, - // editSizeX, ROW_HEIGHT, - // "", ChildId::SSL_MODE_COMBO_BOX); - - // sslModeComboBox->AddString("disable"); - // sslModeComboBox->AddString("require"); - - // sslModeComboBox->SetSelection(sslMode); // set default - // value to require -AL- - - // rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight - // I believe - - val = config.GetReadPreference().c_str(); - - readPreferenceLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Read preference:", ChildId::READ_PREFERENCE_LABEL); - readPreferenceEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, - ChildId::READ_PREFERENCE_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - - val = config.GetReplicaSet().c_str(); - - replicaSetLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Replica Set:", ChildId::REPLICA_SET_LABEL); - replicaSetEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, - ChildId::REPLICA_SET_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - - retryReadsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Retry Reads", ChildId::RETRY_READS_CHECK_BOX, config.IsRetryReads()); - - rowPos += INTERVAL + ROW_HEIGHT; - - tmp = common::LexicalCast(config.GetDefaultFetchSize()); - val = tmp.c_str(); - defaultFetchSizeLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, - ROW_HEIGHT, "Fetch size:", ChildId::DEFAULT_FETCH_SIZE_LABEL); - - defaultFetchSizeEdit = CreateEdit(editPosX, rowPos, editSizeX, - ROW_HEIGHT, val, ChildId::DEFAULT_FETCH_SIZE_EDIT, ES_NUMBER); - - rowPos += INTERVAL + ROW_HEIGHT; - - additionalSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, - "Additional settings", ChildId::ADDITIONAL_SETTINGS_GROUP_BOX); - - return rowPos - posY; - } - */ - int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) { enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also @@ -858,7 +616,6 @@ namespace ignite void DsnConfigurationWindow::RetrieveParameters(config::Configuration& cfg) const { RetrieveConnectionParameters(cfg); - //RetrieveAuthParameters(cfg); RetrieveSshParameters(cfg); RetrieveTlsParameters(cfg); RetrieveAdditionalParameters(cfg); @@ -867,10 +624,7 @@ namespace ignite void DsnConfigurationWindow::RetrieveConnectionParameters(config::Configuration& cfg) const { std::string dsnStr; - //std::string addressStr; std::string schemaStr; - //std::string versionStr; - std::string hostnameStr; std::string portStr; std::string databaseStr; @@ -878,11 +632,8 @@ namespace ignite std::string passwordStr; nameEdit->GetText(dsnStr); - //addressEdit->GetText(addressStr); schemaEdit->GetText(schemaStr); - //protocolVersionComboBox->GetText(versionStr); - //common::StripSurroundingWhitespaces(addressStr); common::StripSurroundingWhitespaces(dsnStr); // Stripping of whitespaces off the schema skipped intentionally @@ -899,9 +650,7 @@ namespace ignite LOG_MSG("Retrieving arguments:"); LOG_MSG("DSN: " << dsnStr); - //LOG_MSG("Address: " << addressStr); LOG_MSG("Schema: " << schemaStr); - //LOG_MSG("Protocol version: " << versionStr); // username and password intentionally not logged for security reasons @@ -910,62 +659,20 @@ namespace ignite diagnostic::DiagnosticRecordStorage diag; - std::vector addresses; - - //config::ParseAddress(addressStr, addresses, &diag); - if (diag.GetStatusRecordsNumber() > 0) { throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, diag.GetStatusRecord(1).GetMessageText().c_str()); } - //ProtocolVersion version = ProtocolVersion::FromString(versionStr); - - /*if (!version.IsSupported()) - throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "Protocol version is not supported.");*/ - cfg.SetDsn(dsnStr); - //cfg.SetAddresses(addresses); cfg.SetDatabase(schemaStr); - //cfg.SetProtocolVersion(version); - - cfg.SetTcpPort(port); - cfg.SetHostname(hostnameStr); - cfg.SetDatabase(databaseStr); - cfg.SetUser(userStr); - cfg.SetPassword(passwordStr); - } - - // comment out because no longer needed - /* - void DsnConfigurationWindow::RetrieveAuthParameters(config::Configuration& cfg) const - { - std::string hostnameStr; - std::string portStr; - std::string databaseStr; - std::string userStr; - std::string passwordStr; - - hostnameEdit->GetText(hostnameStr); - portEdit->GetText(portStr); - databaseEdit->GetText(databaseStr); - userEdit->GetText(userStr); - passwordEdit->GetText(passwordStr); - - int16_t port = - common::LexicalCast(portStr); - - if (port <= 0) - port = config.GetTcpPort(); - cfg.SetTcpPort(port); cfg.SetHostname(hostnameStr); cfg.SetDatabase(databaseStr); cfg.SetUser(userStr); cfg.SetPassword(passwordStr); } - */ void DsnConfigurationWindow::RetrieveSshParameters(config::Configuration& cfg) const { From e30676cdda00f507394da97c273eedc1bc8c230f Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 14:40:08 -0800 Subject: [PATCH 075/165] [AD-522] remove std::auto_ptr authSettingsGroupBox; --- .../include/ignite/odbc/system/ui/dsn_configuration_window.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index dbca6bd5a..d6ceed592 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -234,9 +234,6 @@ namespace ignite /** TLS settings group box. */ std::auto_ptr tlsSettingsGroupBox; - ///** Authentication settings group box. */ - //std::auto_ptr authSettingsGroupBox; - /** Additional settings group box. */ std::auto_ptr additionalSettingsGroupBox; From de64d8707055d3e8f87f5fa2e6b215448ba2aceb Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 14:43:00 -0800 Subject: [PATCH 076/165] [AD-522] remove address field auto pointer initialization --- .../ignite/odbc/system/ui/dsn_configuration_window.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index d6ceed592..15082df8a 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -243,12 +243,6 @@ namespace ignite /** DSN name edit field. */ std::auto_ptr nameEdit; - /** DSN address edit field label. */ - std::auto_ptr addressLabel; - - /** DSN address edit field. */ - std::auto_ptr addressEdit; - /** DSN schema edit field label. */ std::auto_ptr schemaLabel; From f96413deae3de0af108453412b009fceb5d3c6eb Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 14:43:28 -0800 Subject: [PATCH 077/165] [AD-522] remove address field from config window constructor --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index aa2e950cd..f1d5188d7 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -46,8 +46,6 @@ namespace ignite additionalSettingsGroupBox(), nameLabel(), nameEdit(), - addressLabel(), - addressEdit(), schemaLabel(), schemaEdit(), // internal SSH tunnel vars From 4acad7bc7c9c33c640df98df7990fe8a12abc9c9 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 16:21:53 -0800 Subject: [PATCH 078/165] [AD-522] refactor - remove unneeded commented out code in HasText --- src/odbc/os/win/src/system/ui/window.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/window.cpp b/src/odbc/os/win/src/system/ui/window.cpp index 097dee836..02d62e2d8 100644 --- a/src/odbc/os/win/src/system/ui/window.cpp +++ b/src/odbc/os/win/src/system/ui/window.cpp @@ -159,19 +159,9 @@ namespace ignite SNDMSG(handle, WM_SETTEXT, 0, reinterpret_cast(text.c_str())); } - bool Window::HasText() const { + bool Window::HasText() const + { return IsEnabled() && GetWindowTextLength(handle) > 0; - //if (!IsEnabled()) { - // return false; - //} - - //int len = GetWindowTextLength(handle); - - //if (len <= 0) { - // return false; - //} - - //return true; } bool Window::IsChecked() const From 7652d8674be8a74e18e5595d128b3d8b5d345d0e Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 16:23:50 -0800 Subject: [PATCH 079/165] [AD-522] refactor - remove white spaces and update comment --- .../ignite/odbc/system/ui/dsn_configuration_window.h | 2 +- .../os/win/src/system/ui/dsn_configuration_window.cpp | 8 +------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 15082df8a..451badde3 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -297,7 +297,7 @@ namespace ignite /** Login Timeout (seconds) label. */ std::auto_ptr loginTimeoutSecLabel; - /** Nested Read Preference ComboBox **/ + /** Read Preference ComboBox **/ std::auto_ptr readPreferenceComboBox; /** Read preference label. */ diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index f1d5188d7..f132c5617 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -320,7 +320,7 @@ namespace ignite } int DsnConfigurationWindow::CreateTlsSettingsGroup(int posX, int posY, int sizeX) - { // TODO: rename function name from Ssl to TLS after UI works + { enum { LABEL_WIDTH = 100 }; @@ -331,7 +331,6 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; - //int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; // original int checkBoxSize = sizeX - 2 * MARGIN; tlsCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, @@ -481,7 +480,6 @@ namespace ignite return rowPos - posY; } - bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) @@ -705,12 +703,10 @@ namespace ignite cfg.SetSshPrivateKeyPassphrase(sshPrivateKeyPassphraseStr); cfg.SetSshStrictHostKeyChecking(sshStrictHostKeyChecking); cfg.SetSshKnownHostsFile(sshKnownHostsFileStr); - } void DsnConfigurationWindow::RetrieveTlsParameters(config::Configuration& cfg) const { - bool tls = tlsCheckBox->IsChecked(); bool tlsAllowInvalidHostnames = tlsAllowInvalidHostnamesCheckBox->IsChecked(); std::string tlsCaStr; @@ -729,7 +725,6 @@ namespace ignite void DsnConfigurationWindow::RetrieveAdditionalParameters(config::Configuration& cfg) const { - std::string readPreferenceStr; std::string appNameStr; std::string replicaSetStr; @@ -777,7 +772,6 @@ namespace ignite cfg.SetLoginTimeoutSeconds(loginTimeoutSec); cfg.SetReplicaSet(replicaSetStr); cfg.SetDefaultFetchSize(fetchSize); - } } } From 3e01d10eaf2413acfdb3f7685b49f9dff5c92346 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 16:59:10 -0800 Subject: [PATCH 080/165] [AD-522] debug scan_method.h * SpaceToUnderscore is called in scan_method.cpp to make reads better * added guards to scan_method.h --- src/odbc/include/ignite/odbc/scan_method.h | 8 ++++++-- .../os/win/src/system/ui/dsn_configuration_window.cpp | 1 + src/odbc/src/scan_method.cpp | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/odbc/include/ignite/odbc/scan_method.h b/src/odbc/include/ignite/odbc/scan_method.h index 1feb2f9ca..e5230f1ce 100644 --- a/src/odbc/include/ignite/odbc/scan_method.h +++ b/src/odbc/include/ignite/odbc/scan_method.h @@ -15,6 +15,9 @@ * limitations under the License. */ +#ifndef _IGNITE_ODBC_SCAN_METHOD +#define _IGNITE_ODBC_SCAN_METHOD + #include namespace ignite @@ -24,7 +27,7 @@ namespace ignite /** Scan method enum. */ struct ScanMethod { - enum class Type + enum Type { RANDOM, @@ -56,4 +59,5 @@ namespace ignite }; } -} +} // namespace ignite +#endif //_IGNITE_ODBC_SCAN_METHOD \ No newline at end of file diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index f132c5617..b9719c9f7 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -20,6 +20,7 @@ #include "ignite/odbc/log.h" #include "ignite/odbc/read_preference.h" +#include "ignite/odbc/scan_method.h" #include "ignite/odbc/system/ui/dsn_configuration_window.h" #include "ignite/odbc/config/config_tools.h" diff --git a/src/odbc/src/scan_method.cpp b/src/odbc/src/scan_method.cpp index 06400dd9a..ef253fa5f 100644 --- a/src/odbc/src/scan_method.cpp +++ b/src/odbc/src/scan_method.cpp @@ -29,6 +29,8 @@ namespace ignite common::StripSurroundingWhitespaces(lowerVal); + common::SpaceToUnderscore(lowerVal); + if (lowerVal == "random") return ScanMethod::Type::RANDOM; From fa54ad398de475b91769e6a170221ff980c3218a Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 17:02:47 -0800 Subject: [PATCH 081/165] [AD-522] implement Schema group settings box * fixed bug in dsn_config.cpp to save scanLimit correctly --- .../odbc/system/ui/dsn_configuration_window.h | 46 +++++- .../system/ui/dsn_configuration_window.cpp | 147 ++++++++++++++++-- src/odbc/src/dsn_config.cpp | 2 +- 3 files changed, 180 insertions(+), 15 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 451badde3..787e34a1b 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -44,11 +44,10 @@ namespace ignite CONNECTION_SETTINGS_GROUP_BOX = 100, SSH_SETTINGS_GROUP_BOX, TLS_SETTINGS_GROUP_BOX, + SCHEMA_SETTINGS_GROUP_BOX, ADDITIONAL_SETTINGS_GROUP_BOX, NAME_EDIT, NAME_LABEL, - SCHEMA_EDIT, - SCHEMA_LABEL, SSH_ENABLE_CHECK_BOX, SSH_USER_EDIT, SSH_USER_LABEL, @@ -72,6 +71,13 @@ namespace ignite RETRY_READS_CHECK_BOX, DEFAULT_FETCH_SIZE_EDIT, DEFAULT_FETCH_SIZE_LABEL, + SCAN_METHOD_COMBO_BOX, + SCAN_METHOD_LABEL, + SCAN_LIMIT_EDIT, + SCAN_LIMIT_LABEL, + SCHEMA_EDIT, + SCHEMA_LABEL, + REFRESH_SCHEMA_CHECK_BOX, TLS_CHECK_BOX, TLS_ALLOW_INVALID_HOSTNAMES_CHECK_BOX, TLS_CA_FILE_EDIT, @@ -171,6 +177,14 @@ namespace ignite */ void RetrieveTlsParameters(config::Configuration& cfg) const; + /** + * Retrieves current values from the schema generation UI group and + * stores them to the specified configuration. + * + * @param cfg Configuration. + */ + void RetrieveSchemaParameters(config::Configuration& cfg) const; + /** * Retrieves current values from the additional UI group and * stores them to the specified configuration. @@ -209,6 +223,16 @@ namespace ignite */ int CreateTlsSettingsGroup(int posX, int posY, int sizeX); + /** + * Create schema generation settings group box. + * + * @param posX X position. + * @param posY Y position. + * @param sizeX Width. + * @return Size by Y. + */ + int CreateSchemaSettingsGroup(int posX, int posY, int sizeX); + /** * Create additional settings group box. * @@ -234,6 +258,9 @@ namespace ignite /** TLS settings group box. */ std::auto_ptr tlsSettingsGroupBox; + /** Schema generation and discovery settings group box. */ + std::auto_ptr< Window > schemaSettingsGroupBox; + /** Additional settings group box. */ std::auto_ptr additionalSettingsGroupBox; @@ -243,12 +270,27 @@ namespace ignite /** DSN name edit field. */ std::auto_ptr nameEdit; + /** Scan method ComboBox **/ + std::auto_ptr scanMethodComboBox; + + /** Scan method label. */ + std::auto_ptr scanMethodLabel; + + /** Scan limit field label. */ + std::auto_ptr scanLimitLabel; + + /** Scan limit field. */ + std::auto_ptr scanLimitEdit; + /** DSN schema edit field label. */ std::auto_ptr schemaLabel; /** DSN schema edit field. */ std::auto_ptr schemaEdit; + /** Refresh DSN schema checkBox. */ + std::auto_ptr refreshSchemaCheckBox; + /** SSH enable checkBox. */ std::auto_ptr sshEnableCheckBox; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index b9719c9f7..bfbb1ecbc 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -47,8 +47,13 @@ namespace ignite additionalSettingsGroupBox(), nameLabel(), nameEdit(), + scanMethodLabel(), + scanMethodComboBox(), + scanLimitLabel(), + scanLimitEdit(), schemaLabel(), schemaEdit(), + refreshSchemaCheckBox(), // internal SSH tunnel vars sshEnableCheckBox(), sshUserLabel(), @@ -137,6 +142,7 @@ namespace ignite groupPosYLeft += INTERVAL + CreateConnectionSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); //groupPosYLeft += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); groupPosYLeft += INTERVAL + CreateTlsSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); + groupPosYLeft += INTERVAL + CreateSchemaSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); // create right column group settings groupPosYRight += INTERVAL + CreateSshSettingsGroup(posXRight, groupPosYRight, groupSizeY); groupPosYRight += INTERVAL + CreateAdditionalSettingsGroup(posXRight, groupPosYRight, groupSizeY); @@ -225,13 +231,6 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - val = config.GetDatabase().c_str(); - schemaLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Schema Name:", ChildId::SCHEMA_LABEL); - schemaEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SCHEMA_EDIT); - - rowPos += INTERVAL + ROW_HEIGHT; - connectionSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, "Connection Settings", ChildId::CONNECTION_SETTINGS_GROUP_BOX); @@ -363,6 +362,77 @@ namespace ignite return rowPos - posY; } + int DsnConfigurationWindow::CreateSchemaSettingsGroup(int posX, int posY, int sizeX) + { + + enum { LABEL_WIDTH = 100 }; + + int labelPosX = posX + INTERVAL; + + int editSizeX = sizeX - LABEL_WIDTH - 3 * INTERVAL; + int editPosX = labelPosX + LABEL_WIDTH + INTERVAL; + + int rowPos = posY + 2 * INTERVAL; + + int checkBoxSize = sizeX - 2 * MARGIN; + + ScanMethod::Type scanMethod = config.GetScanMethod(); + + scanMethodLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Scan Method:", ChildId::SCAN_METHOD_LABEL); + scanMethodComboBox = CreateComboBox( + editPosX, rowPos, editSizeX, ROW_HEIGHT, + "", ChildId::SCAN_METHOD_COMBO_BOX); + + scanMethodComboBox->AddString("Random"); + scanMethodComboBox->AddString("ID Forward"); + scanMethodComboBox->AddString("ID Reverse"); + scanMethodComboBox->AddString("All"); + + scanMethodComboBox->SetSelection(scanMethod); // set default + + rowPos += INTERVAL + ROW_HEIGHT; + + std::string tmp = common::LexicalCast(config.GetScanLimit()); + const char* val = tmp.c_str(); + scanLimitLabel = CreateLabel( + labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Scan Limit:", ChildId::SCAN_LIMIT_LABEL); + scanLimitEdit = CreateEdit( + editPosX, rowPos, editSizeX, ROW_HEIGHT, + val, ChildId::SCAN_LIMIT_EDIT, ES_NUMBER); + + rowPos += INTERVAL + ROW_HEIGHT; + + val = config.GetDatabase().c_str(); + schemaLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, + "Schema Name:", ChildId::SCHEMA_LABEL); + schemaEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SCHEMA_EDIT); + + rowPos += INTERVAL + ROW_HEIGHT; + + refreshSchemaCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, + "Refresh Schema", ChildId::REFRESH_SCHEMA_CHECK_BOX, config.IsRefreshSchema()); + + rowPos += INTERVAL + ROW_HEIGHT; + + schemaSettingsGroupBox = CreateGroupBox(posX, posY, sizeX, rowPos - posY, + "Schema Generation Settings", ChildId::SCHEMA_SETTINGS_GROUP_BOX); + + std::string scanMethodStr; + scanMethodComboBox->GetText(scanMethodStr); + if (ScanMethod::FromString(scanMethodStr, + ScanMethod::UNKNOWN) + == ScanMethod::ALL) { + scanLimitEdit->SetEnabled(false); + } else { + scanLimitEdit->SetEnabled(true); + } + + return rowPos - posY; + } + int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) { enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also @@ -582,6 +652,29 @@ namespace ignite break; } + case ChildId::SCAN_METHOD_COMBO_BOX: + { + std::string scanMethodStr; + scanMethodComboBox->GetText(scanMethodStr); + if (ScanMethod::FromString( + scanMethodStr, ScanMethod::UNKNOWN) + == ScanMethod::ALL) + { + scanLimitEdit->SetEnabled(false); + } + else + { + scanLimitEdit->SetEnabled(true); + } + break; + } + + case ChildId::REFRESH_SCHEMA_CHECK_BOX: + { + refreshSchemaCheckBox->SetChecked(!refreshSchemaCheckBox->IsChecked()); + break; + } + case ChildId::RETRY_READS_CHECK_BOX: { retryReadsCheckBox->SetChecked(!retryReadsCheckBox->IsChecked()); @@ -615,13 +708,13 @@ namespace ignite RetrieveConnectionParameters(cfg); RetrieveSshParameters(cfg); RetrieveTlsParameters(cfg); + RetrieveSchemaParameters(cfg); RetrieveAdditionalParameters(cfg); } void DsnConfigurationWindow::RetrieveConnectionParameters(config::Configuration& cfg) const { std::string dsnStr; - std::string schemaStr; std::string hostnameStr; std::string portStr; std::string databaseStr; @@ -629,7 +722,6 @@ namespace ignite std::string passwordStr; nameEdit->GetText(dsnStr); - schemaEdit->GetText(schemaStr); common::StripSurroundingWhitespaces(dsnStr); // Stripping of whitespaces off the schema skipped intentionally @@ -646,8 +738,10 @@ namespace ignite port = config.GetTcpPort(); LOG_MSG("Retrieving arguments:"); - LOG_MSG("DSN: " << dsnStr); - LOG_MSG("Schema: " << schemaStr); + LOG_MSG("DSN: " << dsnStr); + LOG_MSG("Hostname: " << hostnameStr); + LOG_MSG("Port: " << portStr); + LOG_MSG("Database: " << databaseStr); // username and password intentionally not logged for security reasons @@ -663,7 +757,6 @@ namespace ignite } cfg.SetDsn(dsnStr); - cfg.SetDatabase(schemaStr); cfg.SetTcpPort(port); cfg.SetHostname(hostnameStr); cfg.SetDatabase(databaseStr); @@ -721,7 +814,37 @@ namespace ignite cfg.SetTls(tls); cfg.SetTlsAllowInvalidHostnames(tlsAllowInvalidHostnames); cfg.SetTlsCaFile(tlsCaStr); + } + + void DsnConfigurationWindow::RetrieveSchemaParameters(config::Configuration& cfg) const + { + std::string scanMethodStr; + std::string scanLimitStr; + std::string schemaStr; + bool refreshSchema = refreshSchemaCheckBox->IsChecked(); + scanMethodComboBox->GetText(scanMethodStr); + scanLimitEdit->GetText(scanLimitStr); + schemaEdit->GetText(schemaStr); + + int32_t scanLimit = + common::LexicalCast(scanLimitStr); + + if (scanLimit <= 0) + scanLimit = config.GetScanLimit(); + + LOG_MSG("Scan method: " << scanMethodStr); + LOG_MSG("Scan limit " << scanLimit); + LOG_MSG("Schema: " << schemaStr); + LOG_MSG("Refresh schema: " << (refreshSchema ? "true" : "false")); + + ScanMethod::Type scanMethod = + ScanMethod::FromString(scanMethodStr, ScanMethod::UNKNOWN); + + cfg.SetScanMethod(scanMethod); + cfg.SetSchemaName(schemaStr); + cfg.SetScanLimit(scanLimit); + cfg.SetRefreshSchema(refreshSchema); } void DsnConfigurationWindow::RetrieveAdditionalParameters(config::Configuration& cfg) const diff --git a/src/odbc/src/dsn_config.cpp b/src/odbc/src/dsn_config.cpp index da7c8cabe..6d1d4006a 100644 --- a/src/odbc/src/dsn_config.cpp +++ b/src/odbc/src/dsn_config.cpp @@ -219,7 +219,7 @@ namespace ignite if (scanLimit.IsSet() && !config.IsScanLimitSet() && scanLimit.GetValue() > 0) - config.SetDefaultFetchSize(scanLimit.GetValue()); + config.SetScanLimit(scanLimit.GetValue()); SettableValue schemaName = ReadDsnString(dsn, ConnectionStringParser::Key::schemaName); From bc752a3fc76f0ab70f4a70acabe496c350eec6f3 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 25 Jan 2022 17:05:09 -0800 Subject: [PATCH 082/165] [AD-522] update readPreference default value to unknown * removed unneeded commented out code * removed unnecessary code to get string value on readPreference --- .../system/ui/dsn_configuration_window.cpp | 28 ++----------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index bfbb1ecbc..86eed8a7d 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -454,30 +454,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - // useful draft code for changing read preference into a - // mode (check JDBC page for available options) - // const char* val = sslModeStr.c_str(); - - // sslModeLabel = CreateLabel(labelPosX, rowPos, - // LABEL_WIDTH, ROW_HEIGHT, - // "SSL Mode:", ChildId::SSL_MODE_LABEL); - // sslModeComboBox = CreateComboBox(editPosX, rowPos, - // editSizeX, ROW_HEIGHT, - // "", ChildId::SSL_MODE_COMBO_BOX); - - // sslModeComboBox->AddString("disable"); - // sslModeComboBox->AddString("require"); - - // sslModeComboBox->SetSelection(sslMode); // set default - // value to require -AL- - - // rowPos += INTERVAL + ROW_HEIGHT; // used to add row hight - // I believe - ReadPreference::Type readPreference = config.GetReadPreference(); - std::string readPreferenceStr = ReadPreference::ToString(readPreference); - - const char* val = readPreferenceStr.c_str(); readPreferenceLabel = CreateLabel( labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, @@ -496,8 +473,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - - val = config.GetApplicationName().c_str(); + const char* val = config.GetApplicationName().c_str(); appNameLabel = CreateLabel( labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Application Name:", ChildId::APP_NAME_LABEL); @@ -888,7 +864,7 @@ namespace ignite LOG_MSG("Fetch size: " << fetchSize); ReadPreference::Type readPreference = ReadPreference::FromString( - readPreferenceStr, ReadPreference::Type::PRIMARY); + readPreferenceStr, ReadPreference::Type::UNKNOWN); cfg.SetReadPreference(readPreference); cfg.SetRetryReads(retryReads); From c7ed03134c82862ea9a3058d7fd93ec0026bdacd Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 26 Jan 2022 09:39:42 -0800 Subject: [PATCH 083/165] [AD-522] refactor - remove unnecessary comments --- .../win/src/system/ui/dsn_configuration_window.cpp | 9 ++++----- src/odbc/src/config/configuration.cpp | 14 +++++++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 86eed8a7d..4121d66c3 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -33,7 +33,7 @@ namespace ignite namespace system { namespace ui - { // -AL- the constructor. No-op means no operation I think? + { DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, config::Configuration& config): CustomWindow(parent, "IgniteConfigureDsn", "Configure Amazon DocumentDB DSN Latest"), //width(360), // original width:360. @@ -42,7 +42,7 @@ namespace ignite //width(360), //height(800), connectionSettingsGroupBox(), - tlsSettingsGroupBox(), // has a create... function defined + tlsSettingsGroupBox(), tlsCheckBox(), additionalSettingsGroupBox(), nameLabel(), @@ -126,7 +126,7 @@ namespace ignite throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, buf.str().c_str()); } } - // the function that actually creates the UI -AL- + void DsnConfigurationWindow::OnCreate() { int groupPosYLeft = MARGIN; @@ -239,7 +239,7 @@ namespace ignite int DsnConfigurationWindow::CreateSshSettingsGroup(int posX, int posY, int sizeX) { - enum { LABEL_WIDTH = 120 }; // -AL- copied from above function + enum { LABEL_WIDTH = 120 }; int labelPosX = posX + INTERVAL; @@ -248,7 +248,6 @@ namespace ignite int rowPos = posY + 2 * INTERVAL; - //int checkBoxSize = (sizeX - 3 * INTERVAL) / 2; // original int checkBoxSize = sizeX - 2 * MARGIN; sshEnableCheckBox = CreateCheckBox( diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 314e67af1..1d025d4e6 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -32,18 +32,18 @@ namespace ignite { // Connection Settings const std::string Configuration::DefaultValue::dsn = "DocumentDB DSN"; - const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB ODBC Driver"; // -AL- add (= need to add to UI) + const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB ODBC Driver"; // driver does not need to be added in config window since it is chosen at the Data Source Administrator - const std::string Configuration::DefaultValue::database = ""; // -AL- add - const std::string Configuration::DefaultValue::hostname = ""; // -AL- add - const uint16_t Configuration::DefaultValue::port = 27017; // -AL- add + const std::string Configuration::DefaultValue::database = ""; + const std::string Configuration::DefaultValue::hostname = ""; + const uint16_t Configuration::DefaultValue::port = 27017; const std::string Configuration::DefaultValue::user = ""; const std::string Configuration::DefaultValue::password = ""; - // SSL/TLS options. Use checkboxes for boolean variables // need to add to UI - const bool Configuration::DefaultValue::tls = true; // changed instead of SSL mode; tls is TLS Encryption + // SSL/TLS options. Use checkboxes for boolean variables + const bool Configuration::DefaultValue::tls = true; const bool Configuration::DefaultValue::tlsAllowInvalidHostnames = false; // needs to be set to true for SSH; TLS Allow Invalid Hostnames - const std::string Configuration::DefaultValue::tlsCaFile = ""; //renamed from SSL CA file + const std::string Configuration::DefaultValue::tlsCaFile = ""; // Schema Generation and Discovery options const ScanMethod::Type Configuration::DefaultValue::scanMethod = ScanMethod::Type::RANDOM; From 0aa20527606ccc11a7a99d6bd6f8d249fa8d1f61 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 26 Jan 2022 09:40:38 -0800 Subject: [PATCH 084/165] [AD-522] adjust window size and additional settings group label size * additional settings group label size is now the same as other settings group in the same column --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 4121d66c3..b3a35c843 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -37,10 +37,10 @@ namespace ignite DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, config::Configuration& config): CustomWindow(parent, "IgniteConfigureDsn", "Configure Amazon DocumentDB DSN Latest"), //width(360), // original width:360. - height(600), // original height:600 + //height(600), // original height:600 width(730), // double the original width //width(360), - //height(800), + height(515), connectionSettingsGroupBox(), tlsSettingsGroupBox(), tlsCheckBox(), @@ -434,7 +434,8 @@ namespace ignite int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) { - enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also + enum { LABEL_WIDTH = 120 }; // same as SSH settings + //enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also // change it to the same int labelPosX = posX + INTERVAL; From df0cad5490612c695ca28cc8ee44c73dbb1b68bd Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 26 Jan 2022 10:35:07 -0800 Subject: [PATCH 085/165] Revert "Merge branch 'develop' into alinaliBQ/AD-522/config_window" This reverts commit 8d609dac52d3e3fc0442f2e8ec8526ec3eb2d6ab, reversing changes made to 0aa20527606ccc11a7a99d6bd6f8d249fa8d1f61. --- .github/workflows/checks.yml | 1 + .github/workflows/mac-build.yml | 26 +- .github/workflows/mac-debug-build.yml | 1 - .github/workflows/win-build.yml | 79 +- README.md | 10 +- build_mac_debug64.sh | 21 - build_mac_release64.sh | 26 +- scripts/build_windows.ps1 | 15 - scripts/register_driver_macos.sh | 27 - .../include/ignite/common/big_integer.h | 2 +- src/common/include/ignite/common/decimal.h | 6 +- src/odbc-test/CMakeLists.txt | 43 +- src/odbc-test/config/ssh_config | 2 - src/odbc-test/include/odbc_test_suite.h | 12 +- src/odbc-test/include/test_utils.h | 47 +- src/odbc-test/src/connection_test.cpp | 86 +- src/odbc-test/src/odbc_test_suite.cpp | 27 +- src/odbc-test/src/test_utils.cpp | 95 +- src/odbc/CMakeLists.txt | 35 +- .../ignite/odbc/app/application_data_buffer.h | 2 +- .../include/ignite/odbc/common/big_integer.h | 526 -------- src/odbc/include/ignite/odbc/common/bits.h | 221 ---- .../include/ignite/odbc/common/concurrent.h | 605 --------- src/odbc/include/ignite/odbc/common/decimal.h | 530 -------- .../ignite/odbc/common/default_allocator.h | 92 -- .../ignite/odbc/common/dynamic_size_array.h | 418 ------- .../include/ignite/odbc/common/expected.h | 303 ----- .../ignite/odbc/common/fixed_size_array.h | 262 ---- .../ignite/odbc/common/platform_utils.h | 126 -- src/odbc/include/ignite/odbc/common/utils.h | 664 ---------- src/odbc/include/ignite/odbc/connection.h | 31 +- src/odbc/include/ignite/odbc/ignite_error.h | 316 ----- src/odbc/include/ignite/odbc/jni/java.h | 641 ---------- src/odbc/include/ignite/odbc/jni/utils.h | 193 --- src/odbc/include/ignite/odbc/log.h | 6 +- .../include/ignite/odbc/meta/column_meta.h | 2 +- .../ignite/odbc/meta/primary_key_meta.h | 2 +- src/odbc/include/ignite/odbc/odbc_error.h | 6 +- src/odbc/include/ignite/odbc/utility.h | 8 +- src/odbc/install/install_amd64.cmd | 3 +- .../linux/include/ignite/odbc/common/common.h | 56 - .../ignite/odbc/common/concurrent_os.h | 701 ----------- .../os/linux/src/common/concurrent_os.cpp | 211 ---- .../os/linux/src/common/platform_utils.cpp | 143 --- .../win/include/ignite/odbc/common/common.h | 46 - .../ignite/odbc/common/concurrent_os.h | 610 --------- src/odbc/os/win/src/common/concurrent_os.cpp | 208 ---- src/odbc/os/win/src/common/platform_utils.cpp | 140 --- src/odbc/os/win/src/system/ui/window.cpp | 8 +- src/odbc/src/app/application_data_buffer.cpp | 2 +- src/odbc/src/common/big_integer.cpp | 866 ------------- src/odbc/src/common/bits.cpp | 236 ---- src/odbc/src/common/concurrent.cpp | 108 -- src/odbc/src/common/decimal.cpp | 278 ----- src/odbc/src/common/utils.cpp | 219 ---- src/odbc/src/connection.cpp | 387 +++--- src/odbc/src/ignite_error.cpp | 227 ---- src/odbc/src/jni/java.cpp | 1102 ----------------- src/odbc/src/jni/os/linux/utils.cpp | 432 ------- src/odbc/src/jni/os/win/utils.cpp | 459 ------- src/odbc/src/log.cpp | 2 +- src/odbc/src/protocol_version.cpp | 2 +- src/odbc/src/ssl_mode.cpp | 2 +- src/odbc/src/utility.cpp | 10 +- 64 files changed, 475 insertions(+), 11498 deletions(-) delete mode 100644 scripts/register_driver_macos.sh delete mode 100644 src/odbc-test/config/ssh_config delete mode 100644 src/odbc/include/ignite/odbc/common/big_integer.h delete mode 100644 src/odbc/include/ignite/odbc/common/bits.h delete mode 100644 src/odbc/include/ignite/odbc/common/concurrent.h delete mode 100644 src/odbc/include/ignite/odbc/common/decimal.h delete mode 100644 src/odbc/include/ignite/odbc/common/default_allocator.h delete mode 100644 src/odbc/include/ignite/odbc/common/dynamic_size_array.h delete mode 100644 src/odbc/include/ignite/odbc/common/expected.h delete mode 100644 src/odbc/include/ignite/odbc/common/fixed_size_array.h delete mode 100644 src/odbc/include/ignite/odbc/common/platform_utils.h delete mode 100644 src/odbc/include/ignite/odbc/common/utils.h delete mode 100644 src/odbc/include/ignite/odbc/ignite_error.h delete mode 100644 src/odbc/include/ignite/odbc/jni/java.h delete mode 100644 src/odbc/include/ignite/odbc/jni/utils.h delete mode 100644 src/odbc/os/linux/include/ignite/odbc/common/common.h delete mode 100644 src/odbc/os/linux/include/ignite/odbc/common/concurrent_os.h delete mode 100644 src/odbc/os/linux/src/common/concurrent_os.cpp delete mode 100644 src/odbc/os/linux/src/common/platform_utils.cpp delete mode 100644 src/odbc/os/win/include/ignite/odbc/common/common.h delete mode 100644 src/odbc/os/win/include/ignite/odbc/common/concurrent_os.h delete mode 100644 src/odbc/os/win/src/common/concurrent_os.cpp delete mode 100644 src/odbc/os/win/src/common/platform_utils.cpp delete mode 100644 src/odbc/src/common/big_integer.cpp delete mode 100644 src/odbc/src/common/bits.cpp delete mode 100644 src/odbc/src/common/concurrent.cpp delete mode 100644 src/odbc/src/common/decimal.cpp delete mode 100644 src/odbc/src/common/utils.cpp delete mode 100644 src/odbc/src/ignite_error.cpp delete mode 100644 src/odbc/src/jni/java.cpp delete mode 100644 src/odbc/src/jni/os/linux/utils.cpp delete mode 100644 src/odbc/src/jni/os/win/utils.cpp diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index ac7484567..d3fec3b10 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -11,3 +11,4 @@ jobs: - uses: ZedThree/clang-tidy-review@v0.7.0 id: review continue-on-error: true + diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index 29368f323..870a2b257 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -12,19 +12,9 @@ on: env: CI_OUTPUT_PATH: "ci-output" - ODBC_LIB_PATH: "${{github.workspace}}/build/odbc/lib" - ODBC_BIN_PATH: "${{github.workspace}}/build/odbc/bin" - ODBC_BUILD_PATH: "${{github.workspace}}/build/odbc/build" - DOCUMENTDB_HOME: "${{github.workspace}}/build/odbc/bin" - DOC_DB_KEYPAIR: ${{secrets.DOC_DB_KEYPAIR}} - DOC_DB_USER_NAME: ${{secrets.DOC_DB_USER_NAME}} - DOC_DB_PASSWORD: ${{secrets.DOC_DB_PASSWORD}} - DOC_DB_USER: ${{secrets.DOC_DB_USER}} - DOC_DB_HOST: ${{secrets.DOC_DB_HOST}} - DOC_DB_LOCAL_PORT: 27019 - DOC_DB_REMOTE_PORT: 27017 - DOC_DB_PRIV_KEY_FILE: ~/certs/docdb-sshtunnel.pem - JDBC_DRIVER_VERSION: "1.1.0" + ODBC_LIB_PATH: "./build/odbc/lib" + ODBC_BIN_PATH: "./build/odbc/bin" + ODBC_BUILD_PATH: "./build/odbc/build" jobs: build-mac: @@ -47,12 +37,6 @@ jobs: # with: # name: cppcheck-results # path: cppcheck-results.log - - name: Extract key-pair into file - run: | - mkdir ~/certs - echo "${{env.DOC_DB_KEYPAIR}}" > ${{env.DOC_DB_PRIV_KEY_FILE}} - chmod 400 ${{env.DOC_DB_PRIV_KEY_FILE}} - - name: get-dependencies run: | brew install unixodbc @@ -70,10 +54,6 @@ jobs: # sudo cp ./src/Tests/Tests/odbc-mac.ini /Library/ODBC/odbc.ini # sudo cp ./src/Tests/Tests/odbcinst-mac.ini /Library/ODBC/odbcinst.ini # mkdir ${{ github.workspace }}/odbc-logs - - name: register-odbc-driver - run: | - chmod +x scripts/register_driver_macos.sh - ./scripts/register_driver_macos.sh - name: run-tests run: | ./build/odbc/bin/ignite-odbc-tests diff --git a/.github/workflows/mac-debug-build.yml b/.github/workflows/mac-debug-build.yml index 8d41ff8fb..85468cd26 100644 --- a/.github/workflows/mac-debug-build.yml +++ b/.github/workflows/mac-debug-build.yml @@ -8,7 +8,6 @@ env: ODBC_LIB_PATH: "./build/odbc/lib" ODBC_BIN_PATH: "./build/odbc/bin" ODBC_BUILD_PATH: "./build/odbc/build" - DOCUMENTDB_HOME: "./build/odbc/bin" jobs: build-mac: diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index b02b4b8f5..ee0506351 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -16,75 +16,45 @@ env: ODBC_BIN_PATH: "./build/odbc/bin/Release" ODBC_BUILD_PATH: "./build/odbc/cmake" VCPKG_ROOT: "c:/vcpkg" - DOCUMENTDB_HOME: "./build/odbc/bin/Release" - DOC_DB_KEYPAIR: ${{secrets.DOC_DB_KEYPAIR}} - DOC_DB_USER_NAME: ${{secrets.DOC_DB_USER_NAME}} - DOC_DB_PASSWORD: ${{secrets.DOC_DB_PASSWORD}} - DOC_DB_USER: ${{secrets.DOC_DB_USER}} - DOC_DB_HOST: ${{secrets.DOC_DB_HOST}} - RUN_REMOTE_INTEGRATION_TESTS: ${{ github.event.inputs.testWithoutDocumnetDb && 'false' || 'true' }} - DOC_DB_LOCAL_PORT: 27019 - DOC_DB_REMOTE_PORT: 27017 - DOC_DB_PRIV_KEY_FILE: ~/certs/docdb-sshtunnel.pem - JDBC_DRIVER_VERSION: "1.1.0" jobs: build-windows32: runs-on: windows-latest steps: - uses: actions/checkout@v2 - - name: Get Java distribution uses: actions/setup-java@v2 with: distribution: 'temurin' java-version: '17' architecture: x86 - - name: "Update path for Java" run: | echo "${{ env.JAVA_HOME }}\bin\server" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: "Update path for WIX Toolset" run: | echo "C:\Program Files (x86)\WiX Toolset v3.11\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Get specific version CMake, v3.20.1 uses: lukka/get-cmake@v3.20.1 - - name: add-msbuild-to-path uses: microsoft/setup-msbuild@v1.0.2 - - - name: Extract key-pair into file - run: | - mkdir -p ~/certs - echo "${{env.DOC_DB_KEYPAIR}}" > ~/certs/docdb-sshtunnel.pem - chmod 400 ~/certs/docdb-sshtunnel.pem - mkdir -p ~/.ssh - copy ./src/odbc-test/config/ssh_config ~/.ssh/config - - #- name: Run SSH tunnel to DocumentDB server - # run: | - # ssh.exe -f -N -i ~/certs/docdb-sshtunnel.pem -L ${{env.DOC_DB_LOCAL_PORT}}:${{secrets.DOC_DB_HOST}}:${{env.DOC_DB_REMOTE_PORT}} ${{secrets.DOC_DB_USER}} - - name: Install dependencies Windows run: vcpkg integrate install; vcpkg install openssl:x86-windows boost-test:x86-windows boost-asio:x86-windows boost-chrono:x86-windows boost-interprocess:x86-windows boost-regex:x86-windows boost-system:x86-windows boost-thread:x86-windows env: VCPKG_ROOT: ${{ env.VCPKG_ROOT }} - - name: configure-and-build-driver run: | .\build_win_release32.ps1 env: OPENSSL_ROOT_DIR: '${{ env.VCPKG_ROOT }}/packages/openssl_x86-windows' - - - name: register-driver - run: | - .\src\odbc\install\install_amd64.cmd ${{env.ODBC_BIN_PATH}}\ignite.odbc.dll ${{env.ODBC_BIN_PATH}}\ignite.odbc.dll - + # - name: import-registry + # run: | + # reg import .\src\Tests\Tests\AWSProfileRegistry_Win32.reg + # reg import .\src\Tests\Tests\IAMRegistry_Win32.reg + # mkdir ${{ github.workspace }}\odbc-logs - name: run-tests run: | - ${{env.ODBC_BIN_PATH}}/ignite-odbc-tests.exe + ${{ env.ODBC_BIN_PATH }}/ignite-odbc-tests.exe # - name: upload-test-report # if: failure() # uses: actions/upload-artifact@v2 @@ -121,58 +91,39 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v2 - - name: Get Java distribution uses: actions/setup-java@v2 with: distribution: 'temurin' java-version: '17' architecture: x64 - - name: "Update path for Java" run: | - echo "${{env.JAVA_HOME}}\bin\server" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - + echo "${{ env.JAVA_HOME }}\bin\server" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: "Update path for WIX Toolset" run: | echo "C:\Program Files (x86)\WiX Toolset v3.11\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Get specific version CMake, v3.20.1 uses: lukka/get-cmake@v3.20.1 - - name: add-msbuild-to-path uses: microsoft/setup-msbuild@v1.0.2 - - - name: Extract key-pair into file - run: | - mkdir -p ~/certs - echo "${{env.DOC_DB_KEYPAIR}}" > ~/certs/docdb-sshtunnel.pem - chmod 400 ~/certs/docdb-sshtunnel.pem - mkdir -p ~/.ssh - copy ./src/odbc-test/config/ssh_config ~/.ssh/config - - #- name: Run SSH tunnel to DocumentDB server - # run: | - # ssh.exe -f -N -i ~/certs/docdb-sshtunnel.pem -L ${{env.DOC_DB_LOCAL_PORT}}:${{secrets.DOC_DB_HOST}}:${{env.DOC_DB_REMOTE_PORT}} ${{secrets.DOC_DB_USER}} - - name: Install dependencies Windows run: vcpkg integrate install; vcpkg install openssl:x64-windows boost-test:x64-windows boost-asio:x64-windows boost-chrono:x64-windows boost-interprocess:x64-windows boost-regex:x64-windows boost-system:x64-windows boost-thread:x64-windows env: - VCPKG_ROOT: ${{env.VCPKG_ROOT}} - + VCPKG_ROOT: ${{ env.VCPKG_ROOT }} - name: configure-and-build-driver run: | .\build_win_release64.ps1 env: - OPENSSL_ROOT_DIR: '${{env.VCPKG_ROOT}}/packages/openssl_x64-windows' - - - name: register-driver - run: | - .\src\odbc\install\install_amd64.cmd ${{env.ODBC_BIN_PATH}}\ignite.odbc.dll - + OPENSSL_ROOT_DIR: '${{ env.VCPKG_ROOT }}/packages/openssl_x64-windows' + # - name: import-registry + # run: | + # reg import .\src\Tests\Tests\AWSProfileRegistry.reg + # reg import .\src\Tests\Tests\IAMRegistry.reg + # mkdir ${{ github.workspace }}\odbc-logs - name: run-tests run: | - ${{env.ODBC_BIN_PATH}}/ignite-odbc-tests.exe + ${{ env.ODBC_BIN_PATH }}/ignite-odbc-tests.exe # - name: upload-test-report # if: failure() # uses: actions/upload-artifact@v2 diff --git a/README.md b/README.md index 7db369e0d..cb1308e83 100644 --- a/README.md +++ b/README.md @@ -25,13 +25,7 @@ 1. E.g.: `.\build_win_debug64.ps1` 2. Navigate to the `build\odbc\cmake` folder to use the generated solution file, `Ignite.C++.sln` to work on source code development and testing. -7. Set the environment variable `DOCUMENTDB_HOME`. On a developer's machine, set it to `\build\odbc\bin\Debug`. The - build script run above, downloads it to the `\build\odbc\bin\Debug\libs` folder. -8. Open a **64-bit** command shell or **64-bit** PowerShell window, **as Administrator**, run the - ``` - \src\odbc\src\install\install_amd64.cmd \buildbuild\odbc\cmake\Debug\ignite.odbc.dll - ``` -8. More details in [`src\DEVNOTES.txt`](src/DEVNOTES.txt). +7. More details in `src\DEVNOTES.txt`. ### MacOS @@ -50,7 +44,7 @@ 2. Run one of the build scripts to create an initial compilation. 1. E.g.: `./build_mac_release64.sh` 2. Navigate to the `build/odbc/lib` folder to use the generated files. -3. More details in [`src\DEVNOTES.txt`](src/DEVNOTES.txt). +3. More details in `src\DEVNOTES.txt`. ### Linux diff --git a/build_mac_debug64.sh b/build_mac_debug64.sh index 1118a04b9..98222f20f 100755 --- a/build_mac_debug64.sh +++ b/build_mac_debug64.sh @@ -1,26 +1,5 @@ - -BUILD_DIR=cmake-build64 -BUILD_TYPE=Debug -PROJECT_DIR=$(pwd) -DRIVER_BIN_DIR="$PROJECT_DIR/build/odbc/bin" - mkdir cmake-build64 cd cmake-build64 cmake ../src -DCMAKE_BUILD_TYPE="Debug" -DCODE_COVERAGE="ON" -DBUILD_SHARED_LIBS="OFF" -DWITH_TESTS="ON" -DWITH_CORE="OFF" -DWITH_ODBC="ON" -cd .. - -# Download the DocumentDB JDBC Driver -JDBC_DRIVER_VERSION="${JDBC_DRIVER_VERSION-1.1.0}" -JDBC_DRIVER_FILENAME="documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" -JDBC_DRIVER_FULLPATH="$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" -export DOCUMENTDB_HOME="$DRIVER_BIN_DIR" -if [ ! -f "$JDBC_DRIVER_FULLPATH" ]; then - mkdir "$DRIVER_BIN_DIR/libs" - echo "Downloading version $JDBC_DRIVER_VERSION of JDBC driver..." - curl -o "$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" -L https://github.com/aws/amazon-documentdb-jdbc-driver/releases/download/v$JDBC_DRIVER_VERSION/$JDBC_DRIVER_FILENAME - echo "Download complete." -fi - -cd cmake-build64 make ccov-all -j 4 cd .. diff --git a/build_mac_release64.sh b/build_mac_release64.sh index ca42d942e..b2f6bb36f 100755 --- a/build_mac_release64.sh +++ b/build_mac_release64.sh @@ -1,25 +1,5 @@ - -BUILD_DIR=cmake-build64 -BUILD_TYPE=Release -PROJECT_DIR=$(pwd) -DRIVER_BIN_DIR="$PROJECT_DIR/build/odbc/bin" - -set -e -mkdir $BUILD_DIR -cd $BUILD_DIR -cmake ../src -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCODE_COVERAGE="OFF" -DBUILD_SHARED_LIBS="OFF" -DWITH_TESTS="ON" -DWITH_CORE="OFF" -DWITH_ODBC="ON" +mkdir cmake-build64 +cd cmake-build64 +cmake ../src -DCMAKE_BUILD_TYPE="Release" -DCODE_COVERAGE="OFF" -DBUILD_SHARED_LIBS="OFF" -DWITH_TESTS="ON" -DWITH_CORE="OFF" -DWITH_ODBC="ON" make -j 4 - -# Download the DocumentDB JDBC Driver -JDBC_DRIVER_VERSION="${JDBC_DRIVER_VERSION-1.1.0}" -JDBC_DRIVER_FILENAME="documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" -JDBC_DRIVER_FULLPATH="$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" -export DOCUMENTDB_HOME="$DRIVER_BIN_DIR" -if [ ! -f "$JDBC_DRIVER_FULLPATH" ]; then - mkdir "$DRIVER_BIN_DIR/libs" - echo "Downloading version $JDBC_DRIVER_VERSION of JDBC driver..." - curl -o "$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" -L https://github.com/aws/amazon-documentdb-jdbc-driver/releases/download/v$JDBC_DRIVER_VERSION/$JDBC_DRIVER_FILENAME - echo "Download complete." -fi - cd .. diff --git a/scripts/build_windows.ps1 b/scripts/build_windows.ps1 index 3118170cf..3e3d72988 100644 --- a/scripts/build_windows.ps1 +++ b/scripts/build_windows.ps1 @@ -28,21 +28,6 @@ Set-Location $CURRENT_DIR $DRIVER_BIN_DIR = "$DRIVER_BUILD_DIR\..\bin\$CONFIGURATION" New-Item -Path $DRIVER_BIN_DIR -ItemType Directory -Force | Out-Null -# Download the JDBC driver -$JDBC_DRIVER_VERSION = if ($JDBC_DRIVER_VERSION -eq $null) { "1.1.0" } else { $JDBC_DRIVER_VERSION } -$JDBC_DRIVER_FILENAME = "documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" -$JDBC_DRIVER_FULLPATH = "$DRIVER_BIN_DIR\libs\$JDBC_DRIVER_FILENAME" -if (-not (Test-Path -Path $JDBC_DRIVER_FULLPATH -PathType Leaf)) { - New-Item -Path "$DRIVER_BIN_DIR\libs" -ItemType Directory -Force | Out-Null - Write-Output "Downloading version $JDBC_DRIVER_VERSION of JDBC driver..." - $progresspreference = 'silentlyContinue' - Invoke-WebRequest ` - https://github.com/aws/amazon-documentdb-jdbc-driver/releases/download/v$JDBC_DRIVER_VERSION/$JDBC_DRIVER_FILENAME ` - -o $JDBC_DRIVER_FULLPATH - $progressPreference = 'Continue' - Write-Output "Download complete." -} - if (Test-Path -Path $DRIVER_BUILD_DIR\$CONFIGURATION) { Copy-Item $DRIVER_BUILD_DIR\$CONFIGURATION\* $DRIVER_BIN_DIR } diff --git a/scripts/register_driver_macos.sh b/scripts/register_driver_macos.sh deleted file mode 100644 index a5f4f6005..000000000 --- a/scripts/register_driver_macos.sh +++ /dev/null @@ -1,27 +0,0 @@ - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done - -SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" - -PROJECT_DIR="$SCRIPT_DIR/.." -ODBC_LIB_PATH="$PROJECT_DIR/build/odbc/lib" -ODBC_LIB_FILENAME="$ODBC_LIB_PATH/libignite-odbc.dylib" - -if [ ! -f "$ODBC_LIB_FILENAME" ] -then - echo "Cannot find ODBC library file: $ODBC_LIB_FILENAME" - exit 1 -fi - -echo "[Apache Ignite]" > "$ODBC_LIB_PATH/ignite-odbc-install.ini" -echo "Description=Apache Ignite" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" -echo "Driver=$ODBC_LIB_FILENAME" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" -echo "Setup=$ODBC_LIB_FILENAME" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" -echo "DriverODBCVer=03.00" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" -echo "FileUsage=0" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" -odbcinst -i -d -f "$ODBC_LIB_PATH/ignite-odbc-install.ini" diff --git a/src/common/include/ignite/common/big_integer.h b/src/common/include/ignite/common/big_integer.h index 66aef6db0..699f59e38 100644 --- a/src/common/include/ignite/common/big_integer.h +++ b/src/common/include/ignite/common/big_integer.h @@ -383,7 +383,7 @@ namespace ignite // Reading number itself. while (is && isdigit(c)) { - part = part * 10 + (static_cast(c) - '0'); + part = part * 10 + (c - '0'); ++partDigits; if (part >= 1000000000000000000U) diff --git a/src/common/include/ignite/common/decimal.h b/src/common/include/ignite/common/decimal.h index 39287264e..d45297a29 100644 --- a/src/common/include/ignite/common/decimal.h +++ b/src/common/include/ignite/common/decimal.h @@ -326,7 +326,7 @@ namespace ignite os << '0'; } - os.write(&magStr[magBegin], static_cast(lastNonZero) - magBegin + 1); + os.write(&magStr[magBegin], lastNonZero - magBegin + 1); } else { @@ -340,7 +340,7 @@ namespace ignite { os << '.'; - os.write(&magStr[static_cast< std::basic_string< char, std::char_traits< char >, std::allocator< char > >::size_type >(magBegin) + dotPos], afterDot); + os.write(&magStr[magBegin + dotPos], afterDot); } } @@ -395,7 +395,7 @@ namespace ignite { if (isdigit(c)) { - part = part * 10 + (static_cast(c) - '0'); + part = part * 10 + (c - '0'); ++partDigits; } else if (c == '.' && scale < 0) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 77294465b..f81e1a103 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -29,27 +29,29 @@ find_package(ODBC REQUIRED) include_directories(SYSTEM ${ODBC_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${JNI_INCLUDE_DIRS}) include_directories(include ../odbc/include ../network/include) -if (WIN32) - include_directories(../odbc/os/win/include) -else () - # TODO: Ensure MacOS is portable. https://bitquill.atlassian.net/browse/AD-525 - include_directories(../odbc/os/linux/include) -endif() set(SOURCES - src/connection_test.cpp src/dummy_test.cpp - src/odbc_test_suite.cpp - src/test_utils.cpp - ../odbc/src/common/concurrent.cpp - ../odbc/src/common/utils.cpp - ../odbc/src/jni/java.cpp + src/configuration_test.cpp + ../odbc/src/config/config_tools.cpp + ../odbc/src/config/configuration.cpp + ../odbc/src/config/connection_info.cpp + ../odbc/src/config/connection_string_parser.cpp + ../odbc/src/scan_method.cpp + ../odbc/src/read_preference.cpp + ../odbc/src/diagnostic/diagnostic_record.cpp + ../odbc/src/diagnostic/diagnostic_record_storage.cpp + ../odbc/src/utility.cpp + ../odbc/src/common_types.cpp + ../odbc/src/app/application_data_buffer.cpp + ../odbc/src/log.cpp # TODO uncomment/rework the tests after get some connectivity and functionalities working. # src/teamcity/teamcity_boost.cpp # src/teamcity/teamcity_messages.cpp # src/parser_test.cpp # src/cursor_test.cpp # src/connection_info_test.cpp +# src/connection_test.cpp # src/application_data_buffer_test.cpp # src/column_test.cpp # src/configuration_test.cpp @@ -58,6 +60,7 @@ set(SOURCES # src/utility_test.cpp # src/queries_test.cpp # src/queries_ssl_test.cpp +# src/test_utils.cpp # src/sql_test_suite_fixture.cpp # src/sql_string_functions_test.cpp # src/sql_numeric_functions_test.cpp @@ -73,6 +76,7 @@ set(SOURCES # src/api_robustness_test.cpp # src/attributes_test.cpp # src/errors_test.cpp +# src/odbc_test_suite.cpp # src/types_test.cpp # src/transaction_test.cpp # src/authentication_test.cpp @@ -103,21 +107,6 @@ set(SOURCES # ../odbc/src/nested_tx_mode.cpp ) -if (WIN32) - list(APPEND SOURCES - ../odbc/os/win/src/common/concurrent_os.cpp - ../odbc/os/win/src/common/platform_utils.cpp - ../odbc/src/jni/os/win/utils.cpp - ) -else() - # TODO: Ensure MacOS is portable. https://bitquill.atlassian.net/browse/AD-525 - list(APPEND SOURCES - ../odbc/os/linux/src/common/concurrent_os.cpp - ../odbc/os/linux/src/common/platform_utils.cpp - ../odbc/src/jni/os/linux/utils.cpp - ) -endif() - add_executable(${TARGET} ${SOURCES}) target_link_libraries(${TARGET} ${Boost_LIBRARIES} ignite ${ODBC_LIBRARY}) diff --git a/src/odbc-test/config/ssh_config b/src/odbc-test/config/ssh_config deleted file mode 100644 index 6318ba0a5..000000000 --- a/src/odbc-test/config/ssh_config +++ /dev/null @@ -1,2 +0,0 @@ -Host * - StrictHostKeyChecking no diff --git a/src/odbc-test/include/odbc_test_suite.h b/src/odbc-test/include/odbc_test_suite.h index 6bd00a63a..1bdd3b077 100644 --- a/src/odbc-test/include/odbc_test_suite.h +++ b/src/odbc-test/include/odbc_test_suite.h @@ -75,9 +75,7 @@ namespace ignite * @param connectStr Connection string. * @return SQL State. */ - std::string ExpectConnectionReject( - const std::string& connectStr, - const std::string& expectedError = "08001: Failed to establish connection with the host."); + std::string ExpectConnectionReject(const std::string& connectStr); /** * Disconnect. @@ -89,6 +87,14 @@ namespace ignite */ void CleanUp(); + /** + * Start additional with the specified name and config. + * + * @param cfg Config path. + * @param name Instance name. + */ + static Ignite StartTestNode(const char* cfg, const char* name); + /** * Constructor. */ diff --git a/src/odbc-test/include/test_utils.h b/src/odbc-test/include/test_utils.h index dc7b01a80..f83b23b0c 100644 --- a/src/odbc-test/include/test_utils.h +++ b/src/odbc-test/include/test_utils.h @@ -27,7 +27,7 @@ #include -#include "ignite/odbc/common/utils.h" +#include "ignite/ignition.h" #define ODBC_THROW_ON_ERROR(ret, type, handle) \ if (!SQL_SUCCEEDED(ret)) \ @@ -160,6 +160,51 @@ namespace ignite_test */ std::string GetTestConfigDir(); + /** + * Initialize configuration for a node. + * + * Inits Ignite node configuration from specified config file. + * Config file is searched in path specified by IGNITE_NATIVE_TEST_CPP_CONFIG_PATH + * environmental variable. + * + * @param cfg Ignite config. + * @param cfgFile Ignite node config file name without path. + */ + void InitConfig(ignite::IgniteConfiguration& cfg, const char* cfgFile); + + /** + * Start Ignite node. + * + * Starts new Ignite node from specified config file. + * Config file is searched in path specified by IGNITE_NATIVE_TEST_CPP_CONFIG_PATH + * environmental variable. + * + * @param cfgFile Ignite node config file name without path. + * @return New node. + */ + ignite::Ignite StartNode(const char* cfgFile); + + /** + * Start Ignite node. + * + * Starts new Ignite node with the specified name and from specified config file. + * Config file is searched in path specified by IGNITE_NATIVE_TEST_CPP_CONFIG_PATH + * environmental variable. + * + * @param cfgFile Ignite node config file name without path. + * @param name Node name. + * @return New node. + */ + ignite::Ignite StartNode(const char* cfgFile, const char* name); + + /** + * Start node with the config for the current platform. + * + * @param cfg Basic config path. Changed to platform config if needed. + * @param name Instance name. + */ + ignite::Ignite StartPlatformNode(const char* cfg, const char* name); + /** * Remove all the LFS artifacts. */ diff --git a/src/odbc-test/src/connection_test.cpp b/src/odbc-test/src/connection_test.cpp index 28714a040..6d4ed9a8e 100644 --- a/src/odbc-test/src/connection_test.cpp +++ b/src/odbc-test/src/connection_test.cpp @@ -15,6 +15,7 @@ * limitations under the License. */ +#include "test_server.h" #ifdef _WIN32 # include #endif @@ -26,10 +27,14 @@ #include +#include "ignite/ignite.h" +#include "ignite/ignition.h" + #include "test_utils.h" #include "odbc_test_suite.h" using namespace ignite; +using namespace ignite::common; using namespace ignite_test; using namespace boost::unit_test; @@ -48,6 +53,14 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite // No-op. } + /** + * Start a node. + */ + void StartNode() + { + StartTestNode("queries-test.xml", "NodeMain"); + } + /** * Execute the query and return an error code. */ @@ -83,25 +96,6 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite return code; } - static void SetConnectionString(std::string& connectionString, - const std::string& username = std::string()) { - // NOTE: Assuming we are using internal SSH tunnel - std::string user = common::GetEnv("DOC_DB_USER_NAME", "documentdb"); - std::string password = common::GetEnv("DOC_DB_PASSWORD", ""); - std::string host = common::GetEnv("DOC_DB_HOST", ""); - std::string port = "27017"; - if (!username.empty()) { - user = username; - } - - connectionString = - "DRIVER={Apache Ignite};" - "ADDRESS=" + host + ":" + port + ";" - "SCHEMA=test;" - "USER=" + user + ";" - "PASSWORD=" + password + ";"; - } - /** * Destructor. */ @@ -111,61 +105,45 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite } }; - BOOST_FIXTURE_TEST_SUITE(ConnectionTestSuite, ConnectionTestSuiteFixture) BOOST_AUTO_TEST_CASE(TestConnectionRestore) { - std::string connectionString; - SetConnectionString(connectionString); + StartNode(); - Connect(connectionString); - Disconnect(); + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache"); - // TODO: [AD-507] Re-enable when querying is supported. - // https://bitquill.atlassian.net/browse/AD-507 + // Check that query was successfully executed. + BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); - //// Check that query was successfully executed. - //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); + // Stop node. + Ignition::StopAll(true); - //// Query execution should throw ODBC error. - //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08S01"); + // Query execution should throw ODBC error. + BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08S01"); - //// Reusing a closed connection should not crash an application. - //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08001"); + // Reusing a closed connection should not crash an application. + BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08001"); - //// Check that connection was restored. - //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); + StartNode(); + // Check that connection was restored. + BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); } BOOST_AUTO_TEST_CASE(TestConnectionMemoryLeak) { - std::string connectionString; - SetConnectionString(connectionString); - - Connect(connectionString); - - // TODO: [AD-507] Re-enable when querying is supported. - // https://bitquill.atlassian.net/browse/AD-507 - // ExecQuery("Select * from Test"); + TestServer testServer(11100); - Disconnect(); -} + testServer.PushHandshakeResponse(true); + testServer.Start(); -BOOST_AUTO_TEST_CASE(TestConnectionInvalidUser) { - std::string connectionString; - SetConnectionString(connectionString, "invaliduser"); + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11100;SCHEMA=cache"); - ExpectConnectionReject(connectionString, "08001: Failed to establish connection with the host.\n" - "Invalid username or password or user is not authorized on database 'test'. " - "Please check your settings. Authorization failed for user 'invaliduser' on database 'admin' with mechanism"); - - // TODO: [AD-507] Re-enable when querying is supported. - // https://bitquill.atlassian.net/browse/AD-507 - // ExecQuery("Select * from Test"); + ExecQuery("Select * from Test"); Disconnect(); + Disconnect(); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/odbc-test/src/odbc_test_suite.cpp b/src/odbc-test/src/odbc_test_suite.cpp index 1b2ece743..bef4639e1 100644 --- a/src/odbc-test/src/odbc_test_suite.cpp +++ b/src/odbc-test/src/odbc_test_suite.cpp @@ -24,9 +24,10 @@ #include +#include "ignite/ignition.h" + #include "test_utils.h" #include "odbc_test_suite.h" -#include using namespace ignite_test; using namespace boost::unit_test; @@ -102,9 +103,7 @@ namespace ignite BOOST_REQUIRE(stmt != NULL); } - std::string OdbcTestSuite::ExpectConnectionReject( - const std::string& connectStr, - const std::string& expectedError) + std::string OdbcTestSuite::ExpectConnectionReject(const std::string& connectStr) { Prepare(); @@ -119,9 +118,6 @@ namespace ignite outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); BOOST_REQUIRE_EQUAL(ret, SQL_ERROR); - BOOST_REQUIRE_EQUAL(expectedError, - GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc) - .substr(0, expectedError.size())); return GetOdbcErrorState(SQL_HANDLE_DBC, dbc); } @@ -158,6 +154,19 @@ namespace ignite } } + Ignite OdbcTestSuite::StartTestNode(const char* cfg, const char* name) + { + std::string config(cfg); + +#ifdef IGNITE_TESTS_32 + // Cutting off the ".xml" part. + config.resize(config.size() - 4); + config += "-32.xml"; +#endif //IGNITE_TESTS_32 + + return StartNode(config.c_str(), name); + } + OdbcTestSuite::OdbcTestSuite(): env(NULL), dbc(NULL), @@ -169,6 +178,8 @@ namespace ignite OdbcTestSuite::~OdbcTestSuite() { CleanUp(); + + Ignition::StopAll(true); } int8_t OdbcTestSuite::GetTestI8Field(int64_t idx) @@ -336,7 +347,7 @@ namespace ignite { BOOST_TEST_CONTEXT("Test index: " << idx) { - odbc::common::FixedSizeArray expected(static_cast(valLen)); + common::FixedSizeArray expected(static_cast(valLen)); GetTestI8ArrayField(idx, expected.GetData(), expected.GetSize()); for (size_t j = 0; j < valLen; ++j) diff --git a/src/odbc-test/src/test_utils.cpp b/src/odbc-test/src/test_utils.cpp index aa4e654b5..bdd32d8af 100644 --- a/src/odbc-test/src/test_utils.cpp +++ b/src/odbc-test/src/test_utils.cpp @@ -19,13 +19,10 @@ #include -#include -#include "ignite/odbc/jni/utils.h" - +#include #include "test_utils.h" - namespace ignite_test { OdbcClientError GetOdbcError(SQLSMALLINT handleType, SQLHANDLE handle) @@ -78,14 +75,14 @@ namespace ignite_test std::string GetTestConfigDir() { - using namespace ignite::odbc; + using namespace ignite; std::string cfgPath = common::GetEnv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH"); if (!cfgPath.empty()) return cfgPath; - std::string home = jni::ResolveDocumentDbHome(); + std::string home = jni::ResolveIgniteHome(); if (home.empty()) return home; @@ -102,20 +99,100 @@ namespace ignite_test return path.str(); } + void InitConfig(ignite::IgniteConfiguration& cfg, const char* cfgFile) + { + using namespace ignite; + + assert(cfgFile != 0); + + cfg.jvmOpts.push_back("-Xdebug"); + cfg.jvmOpts.push_back("-Xnoagent"); + cfg.jvmOpts.push_back("-Djava.compiler=NONE"); + cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"); + cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError"); + cfg.jvmOpts.push_back("-Duser.timezone=GMT"); + cfg.jvmOpts.push_back("-DIGNITE_QUIET=false"); + cfg.jvmOpts.push_back("-DIGNITE_CONSOLE_APPENDER=false"); + cfg.jvmOpts.push_back("-DIGNITE_UPDATE_NOTIFIER=false"); + cfg.jvmOpts.push_back("-DIGNITE_LOG_CLASSPATH_CONTENT_ON_STARTUP=false"); + cfg.jvmOpts.push_back("-Duser.language=en"); + // Un-comment to debug SSL + //cfg.jvmOpts.push_back("-Djavax.net.debug=ssl"); + + cfg.igniteHome = jni::ResolveIgniteHome(); + cfg.jvmClassPath = jni::CreateIgniteHomeClasspath(cfg.igniteHome, true); + +#ifdef IGNITE_TESTS_32 + cfg.jvmInitMem = 256; + cfg.jvmMaxMem = 768; +#else + cfg.jvmInitMem = 1024; + cfg.jvmMaxMem = 4096; +#endif + + std::string cfgDir = GetTestConfigDir(); + + if (cfgDir.empty()) + throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "Failed to resolve test config directory"); + + std::stringstream path; + + path << cfgDir << common::Fs << cfgFile; + + cfg.springCfgPath = path.str(); + } + + ignite::Ignite StartNode(const char* cfgFile) + { + using namespace ignite; + + IgniteConfiguration cfg; + + InitConfig(cfg, cfgFile); + + return Ignition::Start(cfg); + } + + ignite::Ignite StartNode(const char* cfgFile, const char* name) + { + using namespace ignite; + + assert(name != 0); + + IgniteConfiguration cfg; + + InitConfig(cfg, cfgFile); + + return Ignition::Start(cfg, name); + } + + ignite::Ignite StartPlatformNode(const char* cfg, const char* name) + { + std::string config(cfg); + +#ifdef IGNITE_TESTS_32 + // Cutting off the ".xml" part. + config.resize(config.size() - 4); + config += "-32.xml"; +#endif //IGNITE_TESTS_32 + + return StartNode(config.c_str(), name); + } + std::string AppendPath(const std::string& base, const std::string& toAdd) { std::stringstream stream; - stream << base << ignite::odbc::common::Fs << toAdd; + stream << base << ignite::common::Fs << toAdd; return stream.str(); } void ClearLfs() { - std::string home = ignite::odbc::jni::ResolveDocumentDbHome(); + std::string home = ignite::jni::ResolveIgniteHome(); std::string workDir = AppendPath(home, "work"); - ignite::odbc::common::DeletePath(workDir); + ignite::common::DeletePath(workDir); } } diff --git a/src/odbc/CMakeLists.txt b/src/odbc/CMakeLists.txt index 0c6c45caa..e2021f3e7 100644 --- a/src/odbc/CMakeLists.txt +++ b/src/odbc/CMakeLists.txt @@ -20,23 +20,14 @@ project(ignite-odbc) set(TARGET ${PROJECT_NAME}) find_package(ODBC REQUIRED) -find_package(Java REQUIRED) -find_package(JNI REQUIRED) -include(UseJava) -include_directories(SYSTEM ${ODBC_INCLUDE_DIRS} ${JNI_INCLUDE_DIRS}) +include_directories(SYSTEM ${ODBC_INCLUDE_DIRS}) include_directories(include) set(SOURCES src/app/application_data_buffer.cpp src/app/parameter.cpp src/app/parameter_set.cpp src/common_types.cpp - src/common/big_integer.cpp - src/common/bits.cpp - src/common/concurrent.cpp - src/common/decimal.cpp - src/ignite_error.cpp - src/common/utils.cpp src/config/config_tools.cpp src/config/configuration.cpp src/config/connection_info.cpp @@ -46,7 +37,6 @@ set(SOURCES src/app/application_data_buffer.cpp src/diagnostic/diagnosable_adapter.cpp src/diagnostic/diagnostic_record.cpp src/diagnostic/diagnostic_record_storage.cpp - src/jni/java.cpp src/environment.cpp src/meta/column_meta.cpp src/meta/table_meta.cpp @@ -83,37 +73,20 @@ set(SOURCES src/app/application_data_buffer.cpp src/scan_method.cpp) if (WIN32) - set(OS_INCLUDE os/win/include) + include_directories(os/win/include) - list(APPEND SOURCES - os/win/src/system_dsn.cpp + list(APPEND SOURCES os/win/src/system_dsn.cpp os/win/src/system/ui/custom_window.cpp os/win/src/system/ui/dsn_configuration_window.cpp os/win/src/system/ui/window.cpp - os/win/src/common/concurrent_os.cpp - os/win/src/common/platform_utils.cpp - src/jni/os/win/utils.cpp - module.def - ) -else() - set(OS_INCLUDE os/linux/include) - - list(APPEND SOURCES - os/linux/src/common/concurrent_os.cpp - os/linux/src/common/platform_utils.cpp - src/jni/os/linux/utils.cpp - ) + module.def) endif () -include_directories(${OS_INCLUDE}) - - add_library(${TARGET} SHARED ${SOURCES}) set_target_properties(${TARGET} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION}) target_link_libraries(${TARGET} ${ODBC_LIBRARIES}) -target_link_libraries(${TARGET} ${JNI_LIBRARIES}) if (WIN32) target_link_libraries(${TARGET} ignite-common-objlib ignite-binary-objlib ignite-network-objlib odbccp32 shlwapi) diff --git a/src/odbc/include/ignite/odbc/app/application_data_buffer.h b/src/odbc/include/ignite/odbc/app/application_data_buffer.h index af0231b46..50d324488 100644 --- a/src/odbc/include/ignite/odbc/app/application_data_buffer.h +++ b/src/odbc/include/ignite/odbc/app/application_data_buffer.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include "ignite/odbc/common_types.h" #include "ignite/odbc/type_traits.h" diff --git a/src/odbc/include/ignite/odbc/common/big_integer.h b/src/odbc/include/ignite/odbc/common/big_integer.h deleted file mode 100644 index 4e06543a3..000000000 --- a/src/odbc/include/ignite/odbc/common/big_integer.h +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _IGNITE_ODBC_COMMON_BIG_INTEGER -#define _IGNITE_ODBC_COMMON_BIG_INTEGER - -#include - -#include -#include - -#include - -namespace ignite -{ - namespace odbc - { - namespace common - { - /** - * Big integer number implementation. - */ - class IGNITE_IMPORT_EXPORT BigInteger - { - friend class Decimal; - public: - // Magnitude array type. - typedef DynamicSizeArray MagArray; - - /** - * Default constructor. Constructs zero-value big integer. - */ - BigInteger(); - - /** - * Constructs big integer with the specified integer value. - * - * @param val Value. - */ - explicit BigInteger(int64_t val); - - /** - * String constructor. - * - * @param val String to assign. - * @param len String length. - */ - BigInteger(const char* val, int32_t len); - - /** - * String constructor. - * - * @param val String to assign. - */ - explicit BigInteger(const std::string& val) : - sign(1), - mag() - { - AssignString(val); - } - - /** - * Copy constructor. - * - * @param other Other value. - */ - BigInteger(const BigInteger& other); - - /** - * Constructs big integer from the byte array. - * - * @param val Bytes of the integer. Byte order is big-endian. - * @param len Array length. - * @param sign Signum. Can be -1 (negative) or 1 (positive or zero). - * @param bigEndian If true then magnitude is in big-endian. Otherwise - * the byte order of the magnitude considered to be little-endian. - */ - BigInteger(const int8_t* val, int32_t len, int32_t sign, bool bigEndian = true); - - /** - * Constructs big integer with the specified magnitude. - * @warning Magnitude is moved. This mean mag left empty after the call. - * - * @param mag Magnitude. Moved. - * @param sign Sign. Can be 1 or -1. - */ - BigInteger(MagArray& mag, int8_t sign); - - /** - * Assigment operator. - * - * @param other Other value. - * @return *this. - */ - BigInteger& operator=(const BigInteger& other); - - /** - * Assign specified value to this BigInteger. - * - * @param val Value to assign. - */ - void Assign(const BigInteger& val); - - /** - * Assign specified value to this BigInteger. - * - * @param val Value to assign. - */ - void AssignInt64(int64_t val); - - /** - * Assign specified value to this Decimal. - * - * @param val String to assign. - */ - void AssignString(const std::string& val) - { - AssignString(val.data(), static_cast(val.size())); - } - - /** - * Assign specified value to this Decimal. - * - * @param val String to assign. - * @param len String length. - */ - void AssignString(const char* val, int32_t len); - - /** - * Assign specified value to this BigInteger. - * - * @param val Value to assign. - */ - void AssignUint64(uint64_t val); - - /** - * Get number sign. Returns -1 if negative and 1 otherwise. - * - * @return Sign of the number. - */ - int8_t GetSign() const; - - /** - * Swap function for the BigInteger type. - * - * @param other Other instance. - */ - void Swap(BigInteger& other); - - /** - * Get magnitude array. - * - * @return magnitude array. - */ - const MagArray& GetMagnitude() const; - - /** - * Get this number length in bits as if it was positive. - * - * @return Number length in bits. - */ - uint32_t GetBitLength() const; - - /** - * Get precision of the BigInteger. - * - * @return Number of the decimal digits in the decimal representation - * of the value. - */ - int32_t GetPrecision() const; - - /** - * Fills specified buffer with data of this BigInteger converted to - * bytes in big-endian byte order. Sign is not considered when this - * operation is performed. - * - * @param buffer Buffer to fill. - */ - void MagnitudeToBytes(common::FixedSizeArray& buffer) const; - - /** - * Mutates this BigInteger so its value becomes exp power of this. - * - * @param exp Exponent. - */ - void Pow(int32_t exp); - - /** - * Muitiply this to another big integer. - * - * @param other Another instance. Can be *this. - * @param res Result placed there. Can be *this. - */ - void Multiply(const BigInteger& other, BigInteger& res) const; - - /** - * Divide this to another big integer. - * - * @param divisor Divisor. Can be *this. - * @param res Result placed there. Can be *this. - */ - void Divide(const BigInteger& divisor, BigInteger& res) const; - - /** - * Divide this to another big integer. - * - * @param divisor Divisor. Can be *this. - * @param res Result placed there. Can be *this. - * @param rem Remainder placed there. Can be *this. - */ - void Divide(const BigInteger& divisor, BigInteger& res, BigInteger& rem) const; - - /** - * Add unsigned integer number to this BigInteger. - * - * @param x Number to add. - */ - void Add(uint64_t x); - - /** - * Compare this instance to another. - * - * @param other Another instance. - * @param ignoreSign If set to true than only magnitudes are compared. - * @return Comparasion result - 0 if equal, 1 if this is greater, -1 if - * this is less. - */ - int32_t Compare(const BigInteger& other, bool ignoreSign = false) const; - - /** - * Convert to int64_t. - * - * @return int64_t value. - */ - int64_t ToInt64() const; - - /** - * Check whether this value is negative. - * - * @return True if this value is negative and false otherwise. - */ - bool IsNegative() const - { - return sign < 0; - } - - /** - * Check whether this value is zero. - * - * @return True if this value is negative and false otherwise. - */ - bool IsZero() const - { - return mag.GetSize() == 0; - } - - /** - * Check whether this value is positive. - * - * @return True if this value is positive and false otherwise. - */ - bool IsPositive() const - { - return sign > 0 && !IsZero(); - } - - /** - * Rverses sign of this value. - */ - void Negate() - { - if (!IsZero()) - sign = -sign; - } - - /** - * Output operator. - * - * @param os Output stream. - * @param val Value to output. - * @return Reference to the first param. - */ - friend std::ostream& operator<<(std::ostream& os, const BigInteger& val) - { - if (val.IsZero()) - return os << '0'; - - if (val.sign < 0) - os << '-'; - - const int32_t maxResultDigits = 19; - BigInteger maxUintTenPower; - BigInteger res; - BigInteger left; - - maxUintTenPower.AssignUint64(10000000000000000000U); - - std::vector vals; - - val.Divide(maxUintTenPower, left, res); - - if (res.sign < 0) - res.sign = -res.sign; - - if (left.sign < 0) - left.sign = -left.sign; - - vals.push_back(static_cast(res.ToInt64())); - - while (!left.IsZero()) - { - left.Divide(maxUintTenPower, left, res); - - vals.push_back(static_cast(res.ToInt64())); - } - - os << vals.back(); - - for (int32_t i = static_cast(vals.size()) - 2; i >= 0; --i) - { - os.fill('0'); - os.width(maxResultDigits); - - os << vals[i]; - } - - return os; - } - - /** - * Input operator. - * - * @param is Input stream. - * @param val Value to input. - * @return Reference to the first param. - */ - friend std::istream& operator>>(std::istream& is, BigInteger& val) - { - std::istream::sentry sentry(is); - - // Return zero if input failed. - val.AssignInt64(0); - - if (!is) - return is; - - // Current value parts. - uint64_t part = 0; - int32_t partDigits = 0; - int32_t sign = 1; - - BigInteger pow; - BigInteger bigPart; - - // Current char. - int c = is.peek(); - - if (!is) - return is; - - // Checking sign. - if (c == '-' || c == '+') - { - if (c == '-') - sign = -1; - - is.ignore(); - c = is.peek(); - } - - // Reading number itself. - while (is && isdigit(c)) - { - part = part * 10 + (static_cast(c) - '0'); - ++partDigits; - - if (part >= 1000000000000000000U) - { - BigInteger::GetPowerOfTen(partDigits, pow); - val.Multiply(pow, val); - - val.Add(part); - - part = 0; - partDigits = 0; - } - - is.ignore(); - c = is.peek(); - } - - // Adding last part of the number. - if (partDigits) - { - BigInteger::GetPowerOfTen(partDigits, pow); - - val.Multiply(pow, val); - - val.Add(part); - } - - if (sign < 0) - val.Negate(); - - return is; - } - - /** - * Get BigInteger which value is the ten of the specified power. - * - * @param pow Tenth power. - * @param res Result is placed here. - */ - static void GetPowerOfTen(int32_t pow, BigInteger& res); - - private: - /** - * Add magnitude array to current. - * - * @param addend Addend. - * @param len Length of the addend. - */ - void Add(const uint32_t* addend, int32_t len); - - /** - * Get n-th integer of the magnitude. - * - * @param n Index. - * @return Value of the n-th int of the magnitude. - */ - uint32_t GetMagInt(int32_t n) const; - - /** - * Divide this to another big integer. - * - * @param divisor Divisor. Can be *this. - * @param res Result placed there. Can be *this. - * @param rem Remainder placed there if requested. Can be *this. - * Can be null if the remainder is not needed. - */ - void Divide(const BigInteger& divisor, BigInteger& res, BigInteger* rem) const; - - /** - * Normalizes current value removing trailing zeroes from the magnitude. - */ - void Normalize(); - - /** The sign of this BigInteger: -1 for negative and 1 for non-negative. */ - int8_t sign; - - /** The magnitude of this BigInteger. Byte order is little-endian. */ - MagArray mag; - }; - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if equal. - */ - IGNITE_IMPORT_EXPORT bool operator==(const BigInteger& val1, const BigInteger& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if not equal. - */ - IGNITE_IMPORT_EXPORT bool operator!=(const BigInteger& val1, const BigInteger& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if less. - */ - IGNITE_IMPORT_EXPORT bool operator<(const BigInteger& val1, const BigInteger& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if less or equal. - */ - IGNITE_IMPORT_EXPORT bool operator<=(const BigInteger& val1, const BigInteger& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if gretter. - */ - IGNITE_IMPORT_EXPORT bool operator>(const BigInteger& val1, const BigInteger& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if gretter or equal. - */ - IGNITE_IMPORT_EXPORT bool operator>=(const BigInteger& val1, const BigInteger& val2); - } - } -} - -#endif //_IGNITE_ODBC_COMMON_BIG_INTEGER diff --git a/src/odbc/include/ignite/odbc/common/bits.h b/src/odbc/include/ignite/odbc/common/bits.h deleted file mode 100644 index d53a78e37..000000000 --- a/src/odbc/include/ignite/odbc/common/bits.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _IGNITE_ODBC_COMMON_BITS -#define _IGNITE_ODBC_COMMON_BITS - -#include - -#include -#include - -namespace ignite -{ - namespace odbc - { - namespace common - { - namespace bits - { - /** - * Maximum number of digits in uint64_t number. - */ - const int32_t UINT64_MAX_PRECISION = 20; - - /** - * Get number of trailing zero bits in the two's complement binary - * representation of the specified 32-bit int value. - * - * @param i The value whose bits are to be counted. - * @return The number of trailing zero bits in the two's complement - * binary representation of the specified 32-bit int value. - */ - IGNITE_IMPORT_EXPORT int32_t NumberOfTrailingZerosI32(int32_t i); - - /** - * Get number of leading zero bits in the two's complement binary - * representation of the specified 32-bit int value. - * - * @param i The value whose bits are to be counted. - * @return The number of leading zero bits in the two's complement - * binary representation of the specified 32-bit int value. - */ - IGNITE_IMPORT_EXPORT int32_t NumberOfLeadingZerosI32(int32_t i); - - /** - * Get number of leading zero bits in the two's complement binary - * representation of the specified 32-bit int value. - * - * @param i The value whose bits are to be counted. - * @return The number of leading zero bits in the two's complement - * binary representation of the specified 32-bit int value. - */ - IGNITE_IMPORT_EXPORT int32_t NumberOfLeadingZerosU32(uint32_t i); - - /** - * Get number of leading zero bits in the two's complement binary - * representation of the specified 64-bit int value. - * - * @param i The value whose bits are to be counted. - * @return The number of leading zero bits in the two's complement - * binary representation of the specified 64-bit int value. - */ - IGNITE_IMPORT_EXPORT int32_t NumberOfLeadingZerosI64(int64_t i); - - /** - * Get number of leading zero bits in the two's complement binary - * representation of the specified 64-bit int value. - * - * @param i The value whose bits are to be counted. - * @return The number of leading zero bits in the two's complement - * binary representation of the specified 64-bit int value. - */ - IGNITE_IMPORT_EXPORT int32_t NumberOfLeadingZerosU64(uint64_t i); - - /** - * Get the number of one-bits in the two's complement binary - * representation of the specified 32-bit int value. - * - * @param i The value whose bits are to be counted. - * @return The number of one-bits in the two's complement binary - * representation of the specified 32-bit int value. - */ - IGNITE_IMPORT_EXPORT int32_t BitCountI32(int32_t i); - - /** - * Get bit length for the specified signed 32-bit int value. - * - * @param i The value to get bit length for. - * @return The number of significant bits in the two's complement binary - * representation of the specified 32-bit int value. - */ - IGNITE_IMPORT_EXPORT int32_t BitLengthI32(int32_t i); - - /** - * Get bit length for the specified unsigned 32-bit int value. - * - * @param i The value to get bit length for. - * @return The number of significant bits in the two's complement binary - * representation of the specified 32-bit int value. - */ - IGNITE_IMPORT_EXPORT int32_t BitLengthU32(uint32_t i); - - /** - * Calcutale capasity for required size. - * Rounds up to the nearest power of two. - * - * @param size Needed capasity. - * @return Recomended capasity to allocate. - */ - IGNITE_IMPORT_EXPORT int32_t GetCapasityForSize(int32_t size); - - /** - * Get the number of decimal digits of the integer value. - * - * @param x The value. - * @return The number of decimal digits of the integer value. - */ - IGNITE_IMPORT_EXPORT int32_t DigitLength(uint64_t x); - - /** - * Get n-th power of ten. - * - * @param n Power. Should be in range [0, UINT64_MAX_PRECISION] - * @return 10 pow n, if n is in range [0, UINT64_MAX_PRECISION]. - * Otherwise, behaviour is undefined. - */ - IGNITE_IMPORT_EXPORT uint64_t TenPowerU64(int32_t n); - - /** - * Get the signum function of the specified 64-bit integer value. - * The return value is -1 if the specified value is negative; 0 if the - * specified value is zero; and 1 if the specified value is positive. - * - * @param i the value whose signum is to be computed - * @return The signum function of the specified value. - */ - inline int32_t Signum64(int64_t i) - { - return (static_cast(-i) >> 63) | (i >> 63); - } - - /** - * Makes single 64-bit integer number out of two 32-bit numbers. - * - * @param higher Higher bits part. - * @param lower Lower bits part. - * @return New 64-bit integer. - */ - inline uint64_t MakeU64(uint32_t higher, uint32_t lower) - { - return (static_cast(higher) << 32) | lower; - } - - /** - * Makes single 64-bit integer number out of two 32-bit numbers. - * - * @param higher Higher bits part. - * @param lower Lower bits part. - * @return New 64-bit integer. - */ - inline int64_t MakeI64(uint32_t higher, uint32_t lower) - { - return static_cast(MakeU64(higher, lower)); - } - - /** - * Makes single 32-bit integer number out of two 32-bit numbers, - * shifted by specified number of bits. First number x is shifted - * to the left. - * x y - * [........][........] - * ^[........] - * n res - * - * @param x First part. - * @param y Second part. - * @param n Number of bits to shift. - * @return New 32-bit integer. - */ - inline uint32_t MakeU32(uint32_t x, uint32_t y, int32_t n) - { - return (x << n) | (y >> (32 - n)); - } - - /** - * Makes single 32-bit integer number out of two 32-bit numbers, - * shifted by specified number of bits. First number x is shifted - * to the left. - * x y - * [........][........] - * ^[........] - * n res - * - * @param x First part. - * @param y Second part. - * @param n Number of bits to shift. - * @return New 32-bit integer. - */ - inline int32_t MakeI32(uint32_t x, uint32_t y, int32_t n) - { - return static_cast(MakeU32(x, y, n)); - } - } - } - } -} - -#endif //_IGNITE_ODBC_COMMON_BITS diff --git a/src/odbc/include/ignite/odbc/common/concurrent.h b/src/odbc/include/ignite/odbc/common/concurrent.h deleted file mode 100644 index c0615f22a..000000000 --- a/src/odbc/include/ignite/odbc/common/concurrent.h +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _IGNITE_ODBC_COMMON_CONCURRENT -#define _IGNITE_ODBC_COMMON_CONCURRENT - -#include -#include - -#include "ignite/odbc/common/concurrent_os.h" - -namespace ignite -{ - namespace odbc - { - namespace common - { - namespace concurrent - { - /** - * Type tag for static pointer cast. - */ - struct StaticTag {}; - - /** - * Default deleter implementation. - * - * @param obj Object to be deleted. - */ - template - IGNITE_IMPORT_EXPORT void SharedPointerDefaultDeleter(T* obj) - { - delete obj; - } - - /** - * Empty deleter implementation. - * - * @param obj Object to be deleted. - */ - template - IGNITE_IMPORT_EXPORT void SharedPointerEmptyDeleter(T*) - { - // No-op. - } - - /** - * Holder of shared pointer data. - */ - class IGNITE_IMPORT_EXPORT SharedPointerImpl - { - public: - typedef void(*DeleterType)(void*); - /** - * Constructor. - * - * @param ptr Raw pointer. - */ - SharedPointerImpl(void* ptr, DeleterType deleter); - - /** - * Get raw pointer. - * - * @return Raw pointer. - */ - void* Pointer(); - - /** - * Get raw pointer. - * - * @return Raw pointer. - */ - const void* Pointer() const; - - /** - * Get raw pointer. - * - * @return Raw pointer. - */ - DeleterType Deleter(); - - /** - * Increment usage counter. - */ - void Increment(); - - /** - * Decrement usage counter. - * - * @return True if counter reached zero. - */ - bool Decrement(); - private: - /** Raw pointer. */ - void* ptr; - - /** Deleter. */ - DeleterType deleter; - - /** Reference count. */ - int32_t refCnt; - - IGNITE_NO_COPY_ASSIGNMENT(SharedPointerImpl); - }; - - /* Forward declaration. */ - template - class IGNITE_IMPORT_EXPORT EnableSharedFromThis; - - /* Forward declaration. */ - template - inline void ImplEnableShared(EnableSharedFromThis* some, SharedPointerImpl* impl); - - // Do nothing if the instance is not derived from EnableSharedFromThis. - inline void ImplEnableShared(const volatile void*, const volatile void*) - { - // No-op. - } - - /** - * Shared pointer. - */ - template - class IGNITE_IMPORT_EXPORT SharedPointer - { - public: - friend class EnableSharedFromThis; - - template - friend class SharedPointer; - - /** - * Constructor. - */ - SharedPointer() : - ptr(0), - impl(0) - { - // No-op. - } - - /** - * Constructor. - * - * @param ptr Raw pointer. - * @param deleter Delete function. - */ - SharedPointer(T* ptr, void(*deleter)(T*) = &SharedPointerDefaultDeleter) : - ptr(ptr), - impl(0) - { - if (ptr) - { - impl = new SharedPointerImpl(ptr, reinterpret_cast(deleter)); - ImplEnableShared(ptr, impl); - } - } - - /** - * Constructor. - * - * @param ptr Raw pointer. - * @param deleter Delete function. - */ - template - SharedPointer(T2* ptr, void(*deleter)(T2*) = &SharedPointerDefaultDeleter) : - ptr(ptr), - impl(0) - { - if (ptr) - { - impl = new SharedPointerImpl(ptr, reinterpret_cast(deleter)); - ImplEnableShared(ptr, impl); - } - } - - /** - * Copy constructor. - * - * @param other Instance to copy. - */ - SharedPointer(const SharedPointer& other) : - ptr(other.ptr), - impl(other.impl) - { - if (impl) - impl->Increment(); - } - - /** - * Copy constructor. - * - * @param other Instance to copy. - */ - template - SharedPointer(const SharedPointer& other) : - ptr(other.ptr), - impl(other.impl) - { - if (impl) - impl->Increment(); - } - - /** - * Static-cast constructor. - * - * @param other Instance to copy. - */ - template - SharedPointer(const SharedPointer& other, StaticTag) : - ptr(static_cast(other.ptr)), - impl(other.impl) - { - if (impl) - impl->Increment(); - } - - /** - * Assignment operator. - * - * @param other Other instance. - */ - SharedPointer& operator=(const SharedPointer& other) - { - if (this != &other) - { - SharedPointer tmp(other); - - Swap(tmp); - } - - return *this; - } - - /** - * Assignment operator. - * - * @param other Other instance. - */ - template - SharedPointer& operator=(const SharedPointer& other) - { - SharedPointer tmp(other); - - Swap(tmp); - - return *this; - } - - /** - * Destructor. - */ - ~SharedPointer() - { - if (impl && impl->Decrement()) - { - void* ptr0 = impl->Pointer(); - - void(*deleter)(void*) = impl->Deleter(); - - deleter(ptr0); - - delete impl; - - ptr = 0; - } - } - - /** - * Get raw pointer. - * - * @return Raw pointer. - */ - T* Get() - { - return ptr; - } - - /** - * Get raw pointer. - * - * @return Raw pointer. - */ - const T* Get() const - { - return ptr; - } - - /** - * Check whether underlying raw pointer is valid. - * - * Invalid instance can be returned if some of the previous - * operations have resulted in a failure. For example invalid - * instance can be returned by not-throwing version of method - * in case of error. Invalid instances also often can be - * created using default constructor. - * - * @return True if valid. - */ - bool IsValid() const - { - return impl != 0; - } - - /** - * Swap pointer content with another instance. - * - * @param other Other instance. - */ - void Swap(SharedPointer& other) - { - if (this != &other) - { - T* ptrTmp = ptr; - SharedPointerImpl* implTmp = impl; - - ptr = other.ptr; - impl = other.impl; - - other.ptr = ptrTmp; - other.impl = implTmp; - } - } - - private: - /* Pointer. */ - T* ptr; - - /** Implementation. */ - SharedPointerImpl* impl; - }; - - /** - * Enables static-cast semantics for SharedPointer. - * - * @param val Value to cast. - */ - template - SharedPointer StaticPointerCast(const SharedPointer& val) - { - return SharedPointer(val, StaticTag()); - } - - /** - * The class provides functionality that allows objects of derived - * classes to create instances of shared_ptr pointing to themselves - * and sharing ownership with existing shared_ptr objects. - */ - template - class IGNITE_IMPORT_EXPORT EnableSharedFromThis - { - public: - /** - * Default constructor. - */ - EnableSharedFromThis() : self(0) - { - // No-op. - } - - /** - * Copy constructor. - */ - EnableSharedFromThis(const EnableSharedFromThis&) : self(0) - { - // No-op. - } - - /** - * Assignment operator. - */ - EnableSharedFromThis& operator=(const EnableSharedFromThis&) - { - return *this; - } - - /** - * Destructor. - */ - virtual ~EnableSharedFromThis() - { - // No-op. - } - - /** - * Create shared pointer for this instance. - * - * Can only be called on already shared object. - * @return New shared pointer instance. - */ - SharedPointer SharedFromThis() - { - assert(self != 0); - - SharedPointer ptr; - - ptr.impl = self; - - self->Increment(); - - return ptr; - } - - private: - template - friend void ImplEnableShared(EnableSharedFromThis*, SharedPointerImpl*); - - /** Shared pointer base. */ - SharedPointerImpl* self; - }; - - // Implementation for instances derived from EnableSharedFromThis. - template - inline void ImplEnableShared(EnableSharedFromThis* some, SharedPointerImpl* impl) - { - if (some) - some->self = impl; - } - - /** - * Lock guard. - */ - template - class LockGuard - { - public: - /** - * Constructor. - * - * @param lock Lockable object. - */ - LockGuard(T& lock) : - lock(&lock) - { - lock.Enter(); - } - - /** - * Destructor. - */ - ~LockGuard() - { - if (lock) - lock->Leave(); - } - - /** - * Releases control over lock without unlocking it. - */ - void Forget() - { - lock = 0; - } - - /** - * Releases control over lock and unlocks it as if it would - * go out of scope. - */ - void Reset() - { - if (lock) - { - lock->Leave(); - - Forget(); - } - } - - private: - T* lock; - }; - - typedef LockGuard CsLockGuard; - - /** - * Shared lock guard. - * Locks guard in shared mode. - */ - template - class SharedLockGuard - { - public: - /** - * Constructor. - * - * @param lock Lockable object. - */ - SharedLockGuard(T& lock) : - lock(&lock) - { - lock.LockShared(); - } - - /** - * Destructor. - */ - ~SharedLockGuard() - { - if (lock) - lock->ReleaseShared(); - } - - /** - * Releases control over lock without unlocking it. - */ - void Forget() - { - lock = 0; - } - - /** - * Releases control over lock and unlocks it as if it would - * go out of scope. - */ - void Reset() - { - if (lock) - { - lock->ReleaseShared(); - - Forget(); - } - } - - private: - T* lock; - }; - - typedef SharedLockGuard RwSharedLockGuard; - - /** - * Exclusive lock guard. - * Locks guard in exclusive mode. - */ - template - class ExclusiveLockGuard - { - public: - /** - * Constructor. - * - * @param lock Lockable object. - */ - ExclusiveLockGuard(T& lock) : - lock(&lock) - { - lock.LockExclusive(); - } - - /** - * Destructor. - */ - ~ExclusiveLockGuard() - { - if (lock) - lock->ReleaseExclusive(); - } - - /** - * Releases control over lock without unlocking it. - */ - void Forget() - { - lock = 0; - } - - /** - * Releases control over lock and unlocks it as if it would - * go out of scope. - */ - void Reset() - { - if (lock) - { - lock->ReleaseExclusive(); - - Forget(); - } - } - - private: - T* lock; - }; - - typedef ExclusiveLockGuard RwExclusiveLockGuard; - } // namespace concurrent - } // namespace common - } // namespace odbc -} // namespace ignite - -#endif //_IGNITE_ODBC_COMMON_CONCURRENT diff --git a/src/odbc/include/ignite/odbc/common/decimal.h b/src/odbc/include/ignite/odbc/common/decimal.h deleted file mode 100644 index 9728fc845..000000000 --- a/src/odbc/include/ignite/odbc/common/decimal.h +++ /dev/null @@ -1,530 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _IGNITE_ODBC_COMMON_DECIMAL -#define _IGNITE_ODBC_COMMON_DECIMAL - -#include -#include - -#include -#include - -#include - -namespace ignite -{ - namespace odbc - { - namespace common - { - /** - * Big decimal number implementation. - */ - class IGNITE_IMPORT_EXPORT Decimal - { - public: - /** - * Default constructor. - */ - Decimal(); - - /** - * Constructor. - * - * @param mag Bytes of the magnitude. Should be positive, sign is - * passed using separate argument. - * @param len Magnitude length in bytes. - * @param scale Scale. - * @param sign Sign of the decimal. Should be -1 for negative numbers - * and 1 otherwise. - * @param bigEndian If true then magnitude is in big-endian. Otherwise - * the byte order of the magnitude considered to be little-endian. - */ - Decimal(const int8_t* mag, int32_t len, int32_t scale, int32_t sign, bool bigEndian = true); - - /** - * Copy constructor. - * - * @param other Other instance. - */ - Decimal(const Decimal& other); - - /** - * Integer constructor. - * - * @param val Integer value. - */ - explicit Decimal(int64_t val); - - /** - * Integer constructor with scale. - * - * @param val Integer value. - * @param scale Scale. - */ - Decimal(int64_t val, int32_t scale); - - /** - * BigInteger constructor with scale. - * - * @param val BigInteger value. - * @param scale Scale. - */ - Decimal(const common::BigInteger& val, int32_t scale); - - /** - * String constructor. - * - * @param val String to assign. - * @param len String length. - */ - Decimal(const char* val, int32_t len); - - /** - * String constructor. - * - * @param val String to assign. - */ - explicit Decimal(const std::string& val) : - scale(0), - magnitude(0) - { - AssignString(val); - } - - /** - * Destructor. - */ - ~Decimal(); - - /** - * Copy operator. - * - * @param other Other instance. - * @return This. - */ - Decimal& operator=(const Decimal& other); - - /** - * Convert to double. - */ - operator double() const; - - /** - * Convert to int64_t. - */ - operator int64_t() const; - - /** - * Convert to double. - * - * @return Double value. - */ - double ToDouble() const; - - /** - * Convert to int64_t. - * - * @return int64_t value. - */ - int64_t ToInt64() const; - - /** - * Get scale. - * - * @return Scale. - */ - int32_t GetScale() const; - - /** - * Set scale. - * - * @param scale Scale to set. - * @param res Result is placed here. Can be *this. - */ - void SetScale(int32_t scale, Decimal& res) const; - - /** - * Get precision of the Decimal. - * - * @return Number of the decimal digits in the decimal representation - * of the value. - */ - int32_t GetPrecision() const; - - /** - * Get unscaled value. - * - * @return Unscaled value. - */ - const common::BigInteger& GetUnscaledValue() const; - - /** - * Swap function for the Decimal type. - * - * @param other Other instance. - */ - void Swap(Decimal& second); - - /** - * Get length of the magnitude. - * - * @return Length of the magnitude. - */ - int32_t GetMagnitudeLength() const; - - /** - * Assign specified value to this Decimal. - * - * @param val String to assign. - */ - void AssignString(const std::string& val) - { - AssignString(val.data(), static_cast(val.size())); - } - - /** - * Assign specified value to this Decimal. - * - * @param val String to assign. - * @param len String length. - */ - void AssignString(const char* val, int32_t len); - - /** - * Assign specified value to this Decimal. - * - * @param val Value to assign. - */ - void AssignInt64(int64_t val); - - /** - * Assign specified value to this Decimal. - * - * @param val Value to assign. - */ - void AssignDouble(double val); - - /** - * Assign specified value to this Decimal. - * - * @param val Value to assign. - */ - void AssignUint64(uint64_t val); - - /** - * Compare this instance to another. - * - * @param other Another instance. - * @return Comparasion result - 0 if equal, 1 if this is greater, -1 if - * this is less. - */ - int32_t Compare(const Decimal& other) const; - - /** - * Check whether this value is negative. - * - * @return True if this value is negative and false otherwise. - */ - bool IsNegative() const; - - /** - * Check whether this value is zero. - * - * @return True if this value is negative and false otherwise. - */ - bool IsZero() const; - - /** - * Check whether this value is positive. - * - * @return True if this value is positive and false otherwise. - */ - bool IsPositive() const; - - /** - * Output operator. - * - * @param os Output stream. - * @param val Value to output. - * @return Reference to the first param. - */ - friend std::ostream& operator<<(std::ostream& os, const Decimal& val) - { - const common::BigInteger& unscaled = val.GetUnscaledValue(); - - // Zero magnitude case. Scale does not matter. - if (unscaled.GetMagnitude().IsEmpty()) - return os << '0'; - - // Scale is zero or negative. No decimal point here. - if (val.scale <= 0) - { - os << unscaled; - - // Adding zeroes if needed. - for (int32_t i = 0; i < -val.scale; ++i) - os << '0'; - - return os; - } - - // Getting magnitude as a string. - std::stringstream converter; - - converter << unscaled; - - std::string magStr = converter.str(); - - int32_t magLen = static_cast(magStr.size()); - - int32_t magBegin = 0; - - // If value is negative passing minus sign. - if (magStr[magBegin] == '-') - { - os << magStr[magBegin]; - - ++magBegin; - --magLen; - } - - // Finding last non-zero char. There is no sense in trailing zeroes - // beyond the decimal point. - int32_t lastNonZero = static_cast(magStr.size()) - 1; - - while (lastNonZero >= magBegin && magStr[lastNonZero] == '0') - --lastNonZero; - - // This is expected as we already covered zero number case. - assert(lastNonZero >= magBegin); - - int32_t dotPos = magLen - val.scale; - - if (dotPos <= 0) - { - // Means we need to add leading zeroes. - os << '0' << '.'; - - while (dotPos < 0) - { - ++dotPos; - - os << '0'; - } - - os.write(&magStr[magBegin], static_cast(lastNonZero) - magBegin + 1); - } - else - { - // Decimal point is in the middle of the number. - // Just output everything before the decimal point. - os.write(&magStr[magBegin], dotPos); - - int32_t afterDot = lastNonZero - dotPos - magBegin + 1; - - if (afterDot > 0) - { - os << '.'; - - os.write(&magStr[magBegin + dotPos], afterDot); - } - } - - return os; - } - - /** - * Input operator. - * - * @param is Input stream. - * @param val Value to input. - * @return Reference to the first param. - */ - friend std::istream& operator>>(std::istream& is, Decimal& val) - { - std::istream::sentry sentry(is); - - // Return zero if input failed. - val.AssignInt64(0); - - if (!is) - return is; - - // Current char. - int c = is.peek(); - - // Current value parts. - uint64_t part = 0; - int32_t partDigits = 0; - int32_t scale = -1; - int32_t sign = 1; - - common::BigInteger& mag = val.magnitude; - common::BigInteger pow; - common::BigInteger bigPart; - - if (!is) - return is; - - // Checking sign. - if (c == '-' || c == '+') - { - if (c == '-') - sign = -1; - - is.ignore(); - c = is.peek(); - } - - // Reading number itself. - while (is) - { - if (isdigit(c)) - { - part = part * 10 + (c - '0'); - ++partDigits; - } - else if (c == '.' && scale < 0) - { - // We have found decimal point. Starting counting scale. - scale = 0; - } - else - break; - - is.ignore(); - c = is.peek(); - - if (part >= 1000000000000000000U) - { - common::BigInteger::GetPowerOfTen(partDigits, pow); - mag.Multiply(pow, mag); - - mag.Add(part); - - part = 0; - partDigits = 0; - } - - // Counting scale if the decimal point have been encountered. - if (scale >= 0) - ++scale; - } - - // Adding last part of the number. - if (partDigits) - { - common::BigInteger::GetPowerOfTen(partDigits, pow); - - mag.Multiply(pow, mag); - - mag.Add(part); - } - - // Adjusting scale. - if (scale < 0) - scale = 0; - else - --scale; - - // Reading exponent. - if (c == 'e' || c == 'E') - { - is.ignore(); - - int32_t exp = 0; - is >> exp; - - scale -= exp; - } - - val.scale = scale; - - if (sign < 0) - mag.Negate(); - - return is; - } - - private: - /** Scale. */ - int32_t scale; - - /** Magnitude. */ - common::BigInteger magnitude; - }; - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if equal. - */ - IGNITE_IMPORT_EXPORT bool operator==(const Decimal& val1, const Decimal& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if not equal. - */ - IGNITE_IMPORT_EXPORT bool operator!=(const Decimal& val1, const Decimal& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if less. - */ - IGNITE_IMPORT_EXPORT bool operator<(const Decimal& val1, const Decimal& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if less or equal. - */ - IGNITE_IMPORT_EXPORT bool operator<=(const Decimal& val1, const Decimal& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if gretter. - */ - IGNITE_IMPORT_EXPORT bool operator>(const Decimal& val1, const Decimal& val2); - - /** - * Comparison operator. - * - * @param val1 First value. - * @param val2 Second value. - * @return True if gretter or equal. - */ - IGNITE_IMPORT_EXPORT bool operator>=(const Decimal& val1, const Decimal& val2); - } - } -} - -#endif //_IGNITE_ODBC_COMMON_DECIMAL diff --git a/src/odbc/include/ignite/odbc/common/default_allocator.h b/src/odbc/include/ignite/odbc/common/default_allocator.h deleted file mode 100644 index ddf7bdda7..000000000 --- a/src/odbc/include/ignite/odbc/common/default_allocator.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _IGNITE_ODBC_COMMON_DEFAULT_ALLOCATOR -#define _IGNITE_ODBC_COMMON_DEFAULT_ALLOCATOR - -#include -#include - -#include - -namespace ignite -{ - namespace odbc - { - namespace common - { - /** - * Allocator. Manages objects construction and destruction as well - * as a memory allocation. - */ - template - class IGNITE_IMPORT_EXPORT DefaultAllocator - { - public: - typedef T ValueType; - typedef T* PointerType; - typedef T& ReferenceType; - typedef const T* ConstPointerType; - typedef const T& ConstReferenceType; - typedef int32_t SizeType; - typedef int32_t DifferenceType; - - template struct Rebind - { - typedef DefaultAllocator other; - }; - - /** - * Default constructor. - */ - DefaultAllocator() - { - // No-op. - } - - /** - * Destructor. - */ - ~DefaultAllocator() - { - // No-op. - } - - PointerType Allocate(SizeType len, void* = 0) - { - return static_cast(::operator new(len * sizeof(ValueType))); - } - - void Deallocate(PointerType ptr, SizeType) - { - ::operator delete(ptr); - } - - void Construct(PointerType p, ConstReferenceType val) - { - new (p) ValueType(val); - } - - void Destruct(PointerType p) - { - p->~ValueType(); - } - }; - } - } -} - -#endif // _IGNITE_ODBC_COMMON_DEFAULT_ALLOCATOR diff --git a/src/odbc/include/ignite/odbc/common/dynamic_size_array.h b/src/odbc/include/ignite/odbc/common/dynamic_size_array.h deleted file mode 100644 index 109ccc51c..000000000 --- a/src/odbc/include/ignite/odbc/common/dynamic_size_array.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _IGNITE_ODBC_COMMON_DYNAMIC_SIZE_ARRAY -#define _IGNITE_ODBC_COMMON_DYNAMIC_SIZE_ARRAY - -#include -#include -#include - -#include - -#include -#include -#include - -namespace ignite -{ - namespace odbc - { - namespace common - { - /** - * Dynamic size array is safe container abstraction with a dynamic size. - * This is the analogue of the standard vector. It is needed to be used - * in exported classes as we can't export standard library classes. - */ - template > - class IGNITE_IMPORT_EXPORT DynamicSizeArray - { - public: - typedef T ValueType; - typedef A AllocatorType; - typedef typename AllocatorType::SizeType SizeType; - typedef typename AllocatorType::PointerType PointerType; - typedef typename AllocatorType::ConstPointerType ConstPointerType; - typedef typename AllocatorType::ReferenceType ReferenceType; - typedef typename AllocatorType::ConstReferenceType ConstReferenceType; - - /** - * Default constructor. - * - * Constructs zero-size and zero-capasity array. - */ - DynamicSizeArray(const AllocatorType& allocator = AllocatorType()) : - alloc(allocator), - size(0), - capasity(0), - data(0) - { - // No-op. - } - - /** - * Constructor. - * Constructs empty array with the specified capacity. - * - * @param len Array length. - * @param alloc Allocator. - */ - DynamicSizeArray(SizeType len, const AllocatorType& allocator = AllocatorType()) : - alloc(allocator), - size(0), - capasity(bits::GetCapasityForSize(len)), - data(alloc.Allocate(capasity)) - { - // No-op. - } - - /** - * Raw array constructor. - * - * @param arr Raw array. - * @param len Array length in elements. - */ - DynamicSizeArray(ConstPointerType arr, SizeType len, - const AllocatorType& allocator = AllocatorType()) : - alloc(allocator), - size(0), - capasity(0), - data(0) - { - Assign(arr, len); - } - - /** - * Copy constructor. - * - * @param other Other instance. - */ - DynamicSizeArray(const DynamicSizeArray& other) : - alloc(), - size(0), - capasity(0), - data(0) - { - Assign(other); - } - - /** - * Destructor. - */ - ~DynamicSizeArray() - { - for (PointerType it = data; it != data + size; ++it) - alloc.Destruct(it); - - alloc.Deallocate(data, capasity); - } - - /** - * Assignment operator. - * - * @param other Other instance. - * @return Reference to this instance. - */ - DynamicSizeArray& operator=(const DynamicSizeArray& other) - { - Assign(other); - - return *this; - } - - /** - * Assign new value to the array. - * - * @param other Another array instance. - */ - void Assign(const DynamicSizeArray& other) - { - if (this != &other) - { - alloc = other.alloc; - - Assign(other.GetData(), other.GetSize()); - } - } - - /** - * Assign new value to the array. - * - * @param src Raw array. - * @param len Array length in elements. - */ - void Assign(ConstPointerType src, SizeType len) - { - for (PointerType it = data; it != data + size; ++it) - alloc.Destruct(it); - - if (capasity < len) - { - alloc.Deallocate(data, capasity); - - capasity = bits::GetCapasityForSize(len); - data = alloc.Allocate(capasity); - } - - size = len; - - for (SizeType i = 0; i < size; ++i) - alloc.Construct(data + i, src[i]); - } - - /** - * Append several values to the array. - * - * @param src Raw array. - * @param len Array length in elements. - */ - void Append(ConstPointerType src, SizeType len) - { - Reserve(size + len); - - for (SizeType i = 0; i < len; ++i) - alloc.Construct(data + size + i, src[i]); - - size += len; - } - - /** - * Swap contents of the array with another instance. - * - * @param other Instance to swap with. - */ - void Swap(DynamicSizeArray& other) - { - if (this != &other) - { - std::swap(alloc, other.alloc); - std::swap(size, other.size); - std::swap(capasity, other.capasity); - std::swap(data, other.data); - } - } - - /** - * Get data pointer. - * - * @return Data pointer. - */ - PointerType GetData() - { - return data; - } - - /** - * Get data pointer. - * - * @return Data pointer. - */ - ConstPointerType GetData() const - { - return data; - } - - /** - * Get array size. - * - * @return Array size. - */ - SizeType GetSize() const - { - return size; - } - - /** - * Get capasity. - * - * @return Array capasity. - */ - SizeType GetCapasity() const - { - return capasity; - } - - /** - * Element access operator. - * - * @param idx Element index. - * @return Element reference. - */ - ReferenceType operator[](SizeType idx) - { - assert(idx < size); - - return data[idx]; - } - - /** - * Element access operator. - * - * @param idx Element index. - * @return Element reference. - */ - ConstReferenceType operator[](SizeType idx) const - { - assert(idx < size); - - return data[idx]; - } - - /** - * Check if the array is empty. - * - * @return True if the array is empty. - */ - bool IsEmpty() const - { - return size == 0; - } - - /** - * Clears the array. - */ - void Clear() - { - for (PointerType it = data; it != data + size; ++it) - alloc.Destruct(it); - - size = 0; - } - - /** - * Reserves not less than specified elements number so array is not - * going to grow on append. - * - * @param newCapacity Desired capasity. - */ - void Reserve(SizeType newCapacity) - { - if (capasity < newCapacity) - { - DynamicSizeArray tmp(newCapacity); - - tmp.Assign(*this); - - Swap(tmp); - } - } - - /** - * Resizes array. Destructs elements if the specified size is less - * than the array's size. Default-constructs elements if the - * specified size is more than the array's size. - * - * @param newSize Desired size. - */ - void Resize(SizeType newSize) - { - if (capasity < newSize) - Reserve(newSize); - - if (newSize > size) - { - for (PointerType it = data + size; it < data + newSize; ++it) - alloc.Construct(it, ValueType()); - } - else - { - for (PointerType it = data + newSize; it < data + size; ++it) - alloc.Destruct(it); - } - - size = newSize; - } - - /** - * Get last element. - * - * @return Last element reference. - */ - const ValueType& Back() const - { - assert(size > 0); - - return data[size - 1]; - } - - /** - * Get last element. - * - * @return Last element reference. - */ - ValueType& Back() - { - assert(size > 0); - - return data[size - 1]; - } - - /** - * Get first element. - * - * @return First element reference. - */ - const ValueType& Front() const - { - assert(size > 0); - - return data[0]; - } - - /** - * Get first element. - * - * @return First element reference. - */ - ValueType& Front() - { - assert(size > 0); - - return data[0]; - } - - /** - * Pushes new value to the back of the array, effectively increasing - * array size by one. - * - * @param val Value to push. - */ - void PushBack(ConstReferenceType val) - { - Resize(size + 1); - - Back() = val; - } - - private: - /** Allocator */ - AllocatorType alloc; - - /** Array size. */ - SizeType size; - - /** Array capasity. */ - SizeType capasity; - - /** Data. */ - PointerType data; - }; - } - } -} - -#endif // _IGNITE_ODBC_COMMON_DYNAMIC_SIZE_ARRAY diff --git a/src/odbc/include/ignite/odbc/common/expected.h b/src/odbc/include/ignite/odbc/common/expected.h deleted file mode 100644 index 800fda179..000000000 --- a/src/odbc/include/ignite/odbc/common/expected.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _IGNITE_ODBC_COMMON_EXPECTED -#define _IGNITE_ODBC_COMMON_EXPECTED - -#include - -#include - -namespace ignite -{ - namespace odbc - { - namespace common - { - /** - * Helper class to construct Expected class with error value. - */ - template - struct Unexpected - { - /** Value type. */ - typedef E ValueType; - - /** - * Constructor. - * - * @param e Error value reference. - */ - Unexpected(const ValueType& e) : err(e) - { - // No-op; - } - - /** Error. */ - const ValueType& err; - }; - - /** - * Operation result wrapper. - * - * Represents a type, which can accept one of two value types - expected - * result or error. - * - * @tparam R Result type. - * @tparam E Error type. - * @tparam AR Allocator type used for the Result type. - * @tparam AE Allocator type used for the Error type. - */ - template< - typename R, - typename E, - typename AR = std::allocator, - typename AE = std::allocator > - class Expected - { - public: - /** Result type. */ - typedef R ResultType; - - /** Error type. */ - typedef E ErrorType; - - /** Allocator type used for the ResultType. */ - typedef AR ResultAllocatorType; - - /** Allocator type used for the ErrorType. */ - typedef AE ErrorAllocatorType; - - /** - * Constructor. - * - * Creates new instance, containing expected value. - * @param res Result. - */ - Expected(const ResultType& res) : - ok(true) - { - ResultAllocatorType ral; - - ral.construct(AsResult(), res); - } - - /** - * Constructor. - * - * Creates new instance, containing error. - * @param err Result. - */ - explicit Expected(Unexpected err) : - ok(false) - { - ErrorAllocatorType ral; - - ral.construct(AsError(), err.err); - } - - /** - * Copy constructor. - * - * @param other Other. - */ - Expected(const Expected& other) : - ok(other.ok) - { - if (ok) - { - ResultAllocatorType ral; - - ral.construct(AsResult(), *other.AsResult()); - } - else - { - ErrorAllocatorType ral; - - ral.construct(AsError(), *other.AsError()); - } - } - - /** - * Destructor. - */ - ~Expected() - { - if (ok) - { - ResultAllocatorType ral; - - ral.destroy(AsResult()); - } - else - { - ErrorAllocatorType ral; - - ral.destroy(AsError()); - } - } - - /** - * Check if the value is OK. - * - * @return @c false if the value is an error and @c true otherwise. - */ - bool IsOk() const - { - return ok; - } - - /** - * Get result. Constant accesser. - * - * @return Result if it was set before. - * @throw ErrorType if there is no result. - */ - const ResultType& GetResult() const - { - if (!ok) - throw *AsError(); - - return *AsResult(); - } - - /** - * Get result. - * - * @return Result if it was set before. - * @throw ErrorType if there is no result. - */ - ResultType& GetResult() - { - if (!ok) - throw *AsError(); - - return *AsResult(); - } - - /** - * Get result. Constant accesser. - * - * @return Result if it was set before. - * @throw ErrorType if there is no result. - */ - const ResultType& operator*() const - { - return GetResult(); - } - - /** - * Get result. - * - * @return Result if it was set before. - * @throw ErrorType if there is no result. - */ - ResultType& operator*() - { - return GetResult(); - } - - /** - * Get result. Constant accesser. - * - * @return Result if it was set before. - * @throw ErrorType if there is no result. - */ - const ResultType& operator->() const - { - return GetResult(); - } - - /** - * Get result. - * - * @return Result if it was set before. - * @throw ErrorType if there is no result. - */ - ResultType& operator->() - { - return GetResult(); - } - - /** - * Get error. - * - * @return Error if it was set before. If there is no error, default - * constructed error is returned (which is expected to be "No error"). - */ - const ErrorType& GetError() const - { - static ErrorType noError; - - if (ok) - return noError; - - return *AsError(); - } - - private: - /** - * Get storage as an result. - * - * @return Storage pointer as an result pointer. - */ - ResultType* AsResult() - { - return reinterpret_cast(&storage); - } - - /** - * Get storage as an result. - * - * @return Storage pointer as an result pointer. - */ - const ResultType* AsResult() const - { - return reinterpret_cast(&storage); - } - - /** - * Get storage as an error. - * - * @return Storage pointer as an error pointer. - */ - ErrorType* AsError() - { - return reinterpret_cast(&storage); - } - - /** - * Get storage as an error. - * - * @return Storage pointer as an error pointer. - */ - const ErrorType* AsError() const - { - return reinterpret_cast(&storage); - } - - /** Storage. */ - int8_t storage[sizeof(typename Bigger::type)]; - - /** Result flag. Set to @c false if the value is an error. */ - bool ok; - }; - } - } -} - -#endif // _IGNITE_ODBC_COMMON_EXPECTED \ No newline at end of file diff --git a/src/odbc/include/ignite/odbc/common/fixed_size_array.h b/src/odbc/include/ignite/odbc/common/fixed_size_array.h deleted file mode 100644 index a18a60a84..000000000 --- a/src/odbc/include/ignite/odbc/common/fixed_size_array.h +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _IGNITE_ODBC_COMMON_FIXED_SIZE_ARRAY -#define _IGNITE_ODBC_COMMON_FIXED_SIZE_ARRAY - -#include -#include -#include - -#include -#include - -#include - -namespace ignite -{ - namespace odbc { - namespace common { - /** - * Fixed size array is safe array abstraction with a fixed size. - * The size can be set during runtime though once array is created - * its size can not be changed without resetting arrays content. - */ - template < typename T > - class IGNITE_IMPORT_EXPORT FixedSizeArray { - public: - typedef int32_t SizeType; - - /** - * Default constructor. - * - * Constructs zero-size array. - */ - FixedSizeArray() : size(0), data(0) { - // No-op. - } - - /** - * Constructor. - * Constructs default-initialized array of the specified length. - * Array zeroed if T is a POD type. - * - * @param len Array length. - */ - FixedSizeArray(SizeType len) - : size(len), - // Brackets are here for a purpose - this way allocated - // array is zeroed if T is POD type. - data(new T[size]()) { - // No-op. - } - - /** - * Copy constructor. - * - * @param other Other instance. - */ - FixedSizeArray(const FixedSizeArray< T >& other) - : size(other.size), data(new T[size]) { - Assign(other); - } - - /** - * Raw array constructor. - * - * @param arr Raw array. - * @param len Array length in elements. - */ - FixedSizeArray(const T* arr, SizeType len) : size(len), data(new T[size]) { - Assign(arr, len); - } - - /** - * Assignment operator. - * - * @param other Other instance. - * @return Reference to this instance. - */ - FixedSizeArray< T >& operator=(const FixedSizeArray< T >& other) { - Assign(other); - - return *this; - } - - /** - * Assign new value to the array. - * - * @param other Another array instance. - */ - void Assign(const FixedSizeArray< T >& other) { - if (this != &other) - Assign(other.GetData(), other.GetSize()); - } - - /** - * Assign new value to the array. - * - * @param src Raw array. - * @param len Array length in elements. - */ - void Assign(const T* src, SizeType len) { - // In case we would not need to clean anything - // its okay to call delete[] on 0. - T* toClean = 0; - - if (len != size) { - // Do not clean just yet in case the part of the - // array is being assigned to the array. - toClean = data; - - size = len; - data = new T[size]; - } - - for (SizeType i = 0; i < len; ++i) - data[i] = src[i]; - - delete[] toClean; - } - - /** - * Swap contents of the array with another instance. - * - * @param other Instance to swap with. - */ - void Swap(FixedSizeArray< T >& other) { - if (this != &other) { - std::swap(size, other.size); - std::swap(data, other.data); - } - } - - /** - * Destructor. - */ - ~FixedSizeArray() { - // Not a bug. Delete works just fine on null pointers. - delete[] data; - } - - /** - * Get data pointer. - * - * @return Data pointer. - */ - T* GetData() { - return data; - } - - /** - * Get data pointer. - * - * @return Data pointer. - */ - const T* GetData() const { - return data; - } - - /** - * Get array size. - * - * @return Array size. - */ - SizeType GetSize() const { - return size; - } - - /** - * Copy part of the array and place in another array. - * Contents of the provided array gets swapped with the copy of the - * specified array part. - * - * @param pos Start position. - * @param n Number of elements to copy. - * @param result Instance of an array where result should be placed. - */ - void CopyPart(SizeType pos, SizeType n, FixedSizeArray< T >& result) const { - assert(pos < size); - assert(pos + n <= size); - - result.Assign(data + pos, n); - } - - /** - * Element access operator. - * - * @param idx Element index. - * @return Element reference. - */ - T& operator[](SizeType idx) { - assert(idx < size); - - return data[idx]; - } - - /** - * Element access operator. - * - * @param idx Element index. - * @return Element reference. - */ - const T& operator[](SizeType idx) const { - assert(idx < size); - - return data[idx]; - } - - /** - * Check if the array is empty. - * - * @return True if the array is empty. - */ - bool IsEmpty() const { - return size == 0; - } - - /** - * Resets the state of the array setting it to the specified size - * and erasing its content. - * - * @param newSize New array size. - */ - void Reset(SizeType newSize = 0) { - if (size != newSize) { - delete[] data; - - if (newSize) - data = new T[newSize](); - else - data = 0; - - size = newSize; - } else - std::fill(data, data + size, T()); - } - - private: - /** Array size. */ - SizeType size; - - /** Target array. */ - T* data; - }; - } // namespace common - } // namespace odbc -} - -#endif // _IGNITE_ODBC_COMMON_FIXED_SIZE_ARRAY diff --git a/src/odbc/include/ignite/odbc/common/platform_utils.h b/src/odbc/include/ignite/odbc/common/platform_utils.h deleted file mode 100644 index 5e430de2c..000000000 --- a/src/odbc/include/ignite/odbc/common/platform_utils.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _IGNITE_ODBC_COMMON_PLATFORM_UTILS -#define _IGNITE_ODBC_COMMON_PLATFORM_UTILS - -#include -#include "ignite/odbc/common/common.h" - -namespace ignite -{ - namespace odbc - { - namespace common - { - typedef std::basic_ostream > StdCharOutStream; - - /** - * Convert struct tm to time_t (UTC). - * - * @param time Standard C type struct tm value. - * @return Standard C type time_t value. - */ - IGNITE_IMPORT_EXPORT time_t IgniteTimeGm(const tm& time); - - /** - * Convert struct tm to time_t (Local time). - * - * @param time Standard C type struct tm value. - * @return Standard C type time_t value. - */ - IGNITE_IMPORT_EXPORT time_t IgniteTimeLocal(const tm& time); - - /** - * Convert time_t to struct tm (UTC). - * - * @param in Standard C type time_t value. - * @param out Standard C type struct tm value. - * @return True on success. - */ - IGNITE_IMPORT_EXPORT bool IgniteGmTime(time_t in, tm& out); - - /** - * Convert time_t to struct tm (Local time). - * - * @param in Standard C type time_t value. - * @param out Standard C type struct tm value. - * @return True on success. - */ - IGNITE_IMPORT_EXPORT bool IgniteLocalTime(time_t in, tm& out); - - /** - * Read system environment variable taking thread-safety in count. - * - * @param name Environment variable name. - * @return Environment variable value if found and empty string otherwise. - */ - IGNITE_IMPORT_EXPORT std::string GetEnv(const std::string& name); - - /** - * Read system environment variable taking thread-safety in count. - * - * @param name Environment variable name. - * @param dflt Default value to return on fail. - * @return Environment variable value if found and @c dflt otherwise. - */ - IGNITE_IMPORT_EXPORT std::string GetEnv(const std::string& name, const std::string& dflt); - - /** - * Ensure that file on the given path exists in the system. - * - * @param path Path. - * @return True if file exists, false otherwise. - */ - IGNITE_IMPORT_EXPORT bool FileExists(const std::string& path); - - /** - * Check if the provided path is the valid directory. - * @return @c true if the provided path is the valid directory. - */ - IGNITE_IMPORT_EXPORT bool IsValidDirectory(const std::string& path); - - /** - * Deletes provided filesystem element if exists. - * @return @c true if the provided path exists. - */ - IGNITE_IMPORT_EXPORT bool DeletePath(const std::string& path); - - /** - * Write file separator to a stream. - * @param ostr Stream. - * @return The same stream for chaining. - */ - IGNITE_IMPORT_EXPORT StdCharOutStream& Fs(StdCharOutStream& ostr); - - /** - * Write dynamic library expansion to a stream. - * @param ostr Stream. - * @return The same stream for chaining. - */ - IGNITE_IMPORT_EXPORT StdCharOutStream& Dle(StdCharOutStream& ostr); - - /** - * Get random seed. - * - * @return Random seed. - */ - IGNITE_IMPORT_EXPORT unsigned GetRandSeed(); - } - } -} - -#endif //_IGNITE_ODBC_COMMON_PLATFORM_UTILS diff --git a/src/odbc/include/ignite/odbc/common/utils.h b/src/odbc/include/ignite/odbc/common/utils.h deleted file mode 100644 index accb2fa84..000000000 --- a/src/odbc/include/ignite/odbc/common/utils.h +++ /dev/null @@ -1,664 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _IGNITE_ODBC_COMMON_UTILS -#define _IGNITE_ODBC_COMMON_UTILS - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include "ignite/time.h" - -#ifdef IGNITE_FRIEND -# define IGNITE_FRIEND_EXPORT IGNITE_EXPORT -#else -# define IGNITE_FRIEND_EXPORT -#endif - -namespace ignite -{ - namespace odbc - { - namespace common - { - /** - * Replace all alphabetic symbols of the string with their lowercase - * versions. - * @param str String to be transformed. - */ - inline void IntoLower(std::string& str) - { - std::transform(str.begin(), str.end(), str.begin(), ::tolower); - } - - /** - * Get lowercase version of the string. - * - * @param str Input string. - * @return Lowercased version of the string. - */ - inline std::string ToLower(const std::string& str) - { - std::string res(str); - IntoLower(res); - return res; - } - - /** - * Strips leading and trailing whitespaces from string. - * - * @param str String to be transformed. - */ - IGNITE_IMPORT_EXPORT void StripSurroundingWhitespaces(std::string& str); - - /** - * Skip leading spaces. - * - * @param begin Iterator to the beginning of the character sequence. - * @param end Iterator to the end of the character sequence. - * @return Iterator to first non-blanc character. - */ - template - Iterator SkipLeadingSpaces(Iterator begin, Iterator end) - { - Iterator res = begin; - - while (isspace(*res) && res != end) - ++res; - - return res; - } - - /** - * Skip trailing spaces. - * - * @param begin Iterator to the beginning of the character sequence. - * @param end Iterator to the end of the character sequence. - * @return Iterator to last non-blanc character. - */ - template - Iterator SkipTrailingSpaces(Iterator begin, Iterator end) - { - Iterator res = end - 1; - - while (isspace(*res) && res != begin - 1) - --res; - - return res + 1; - } - - /** - * Remove leading and trailing spaces. - * - * @param begin Iterator to the beginning of the character sequence. - * @param end Iterator to the end of the character sequence. - * @return String without leading and trailing spaces. - */ - template - std::string StripSurroundingWhitespaces(Iterator begin, Iterator end) - { - std::string res; - - if (begin >= end) - return res; - - Iterator skipped_leading = SkipLeadingSpaces(begin, end); - Iterator skipped_trailing = SkipTrailingSpaces(skipped_leading, end); - - res.reserve(skipped_trailing - skipped_leading); - - std::copy(skipped_leading, skipped_trailing, std::back_inserter(res)); - - return res; - } - - /** - * Get string representation of long in decimal form. - * - * @param val Long value to be converted to string. - * @return String contataining decimal representation of the value. - */ - inline std::string LongToString(long val) - { - std::stringstream tmp; - tmp << val; - return tmp.str(); - } - - /** - * Parse string to try and get int value. - * - * @param str String to be parsed. - * @return String contataining decimal representation of the value. - */ - inline int ParseInt(const std::string& str) - { - return atoi(str.c_str()); - } - - /** - * Copy characters. - * - * @param val Value. - * @return Result. - */ - IGNITE_IMPORT_EXPORT char* CopyChars(const char* val); - - /** - * Release characters. - * - * @param val Value. - */ - IGNITE_IMPORT_EXPORT void ReleaseChars(char* val); - - /** - * Casts value of one type to another type, using stringstream. - * - * @param val Input value. - * @param res Resulted value. - */ - template - void LexicalCast(const T2& val, T1& res) - { - std::stringstream converter; - - converter << val; - converter >> res; - } - - /** - * Casts value of one type to another type, using stringstream. - * - * @param val Input value. - * @return Resulted value. - */ - template - T1 LexicalCast(const T2& val) - { - T1 res; - - LexicalCast(val, res); - - return res; - } - - /** - * Check if all characters are digits. - * - * @param val Value to check. - */ - IGNITE_IMPORT_EXPORT bool AllDigits(const std::string& val); - - /** - * Converts 32-bit integer to big endian format - * - * @param value Input value - * @return Resulting value - */ - IGNITE_IMPORT_EXPORT uint32_t ToBigEndian(uint32_t value); - - /** - * Convert Date type to standard C type time_t. - * - * @param date Date type value. - * @return Corresponding value of time_t. - */ - inline time_t DateToCTime(const Date& date) - { - return static_cast(date.GetSeconds()); - } - - /** - * Convert Timestamp type to standard C type time_t. - * - * @param ts Timestamp type value. - * @return Corresponding value of time_t. - */ - inline time_t TimestampToCTime(const Timestamp& ts) - { - return static_cast(ts.GetSeconds()); - } - - /** - * Convert Time type to standard C type time_t. - * - * @param time Time type value. - * @return Corresponding value of time_t. - */ - inline time_t TimeToCTime(const Time& time) - { - return static_cast(time.GetSeconds()); - } - - /** - * Convert Date type to standard C type time_t. - * - * @param date Date type value. - * @param ctime Corresponding value of struct tm. - * @return True on success. - */ - inline bool DateToCTm(const Date& date, tm& ctime) - { - time_t tmt = DateToCTime(date); - - return common::IgniteGmTime(tmt, ctime); - } - - /** - * Convert Timestamp type to standard C type struct tm. - * - * @param ts Timestamp type value. - * @param ctime Corresponding value of struct tm. - * @return True on success. - */ - inline bool TimestampToCTm(const Timestamp& ts, tm& ctime) - { - time_t tmt = TimestampToCTime(ts); - - return common::IgniteGmTime(tmt, ctime); - } - - /** - * Convert Time type to standard C type struct tm. - * - * @param time Time type value. - * @param ctime Corresponding value of struct tm. - * @return True on success. - */ - inline bool TimeToCTm(const Time& time, tm& ctime) - { - time_t tmt = TimeToCTime(time); - - return common::IgniteGmTime(tmt, ctime); - } - - /** - * Convert standard C type time_t to Date. - * - * @param ctime Standard C type time_t. - * @return Corresponding value of Date. - */ - inline Date CTimeToDate(time_t ctime) - { - return Date(ctime * 1000); - } - - /** - * Convert standard C type time_t to Time. - * - * @param ctime Standard C type time_t. - * @return Corresponding value of Time. - */ - inline Time CTimeToTime(time_t ctime) - { - return Time(ctime * 1000); - } - - /** - * Convert standard C type time_t to Timestamp type. - * - * @param ctime Standard C type time_t. - * @param ns Nanoseconds second fraction. - * @return Corresponding value of Timestamp. - */ - inline Timestamp CTimeToTimestamp(time_t ctime, int32_t ns) - { - return Timestamp(ctime, ns); - } - - /** - * Convert standard C type struct tm to Date type. - * - * @param ctime Standard C type struct tm. - * @return Corresponding value of Date. - */ - inline Date CTmToDate(const tm& ctime) - { - time_t time = common::IgniteTimeGm(ctime); - - return CTimeToDate(time); - } - - /** - * Convert standard C type struct tm to Time type. - * - * @param ctime Standard C type struct tm. - * @return Corresponding value of Time. - */ - inline Time CTmToTime(const tm& ctime) - { - time_t time = common::IgniteTimeGm(ctime); - - return CTimeToTime(time); - } - - /** - * Convert standard C type struct tm to Timestamp type. - * - * @param ctime Standard C type struct tm. - * @param ns Nanoseconds second fraction. - * @return Corresponding value of Timestamp. - */ - inline Timestamp CTmToTimestamp(const tm& ctime, int32_t ns) - { - time_t time = common::IgniteTimeGm(ctime); - - return CTimeToTimestamp(time, ns); - } - - /** - * Make Date in human understandable way. - * - * Created Date uses GMT timezone. - * - * @param year Year. - * @param month Month. - * @param day Day. - * @param hour Hour. - * @param min Min. - * @param sec Sec. - * @return Date. - */ - IGNITE_FRIEND_EXPORT Date MakeDateGmt(int year = 1900, int month = 1, - int day = 1, int hour = 0, int min = 0, int sec = 0); - - /** - * Make Date in human understandable way. - * - * Created Date uses local timezone. - * - * @param year Year. - * @param month Month. - * @param day Day. - * @param hour Hour. - * @param min Min. - * @param sec Sec. - * @return Date. - */ - IGNITE_FRIEND_EXPORT Date MakeDateLocal(int year = 1900, int month = 1, - int day = 1, int hour = 0, int min = 0, int sec = 0); - - /** - * Make Time in human understandable way. - * - * Created Time uses GMT timezone. - * - * @param hour Hour. - * @param min Minute. - * @param sec Second. - * @return Time. - */ - IGNITE_FRIEND_EXPORT Time MakeTimeGmt(int hour = 0, int min = 0, int sec = 0); - - /** - * Make Time in human understandable way. - * - * Created Time uses Local timezone. - * - * @param hour Hour. - * @param min Minute. - * @param sec Second. - * @return Time. - */ - IGNITE_FRIEND_EXPORT Time MakeTimeLocal(int hour = 0, int min = 0, int sec = 0); - - /** - * Make Timestamp in human understandable way. - * - * Created Timestamp uses GMT timezone. - * - * @param year Year. - * @param month Month. - * @param day Day. - * @param hour Hour. - * @param min Minute. - * @param sec Second. - * @param ns Nanosecond. - * @return Timestamp. - */ - IGNITE_FRIEND_EXPORT Timestamp MakeTimestampGmt(int year = 1900, int month = 1, - int day = 1, int hour = 0, int min = 0, int sec = 0, long ns = 0); - - /** - * Make Date in human understandable way. - * - * Created Timestamp uses Local timezone. - * - * @param year Year. - * @param month Month. - * @param day Day. - * @param hour Hour. - * @param min Minute. - * @param sec Second. - * @param ns Nanosecond. - * @return Timestamp. - */ - IGNITE_FRIEND_EXPORT Timestamp MakeTimestampLocal(int year = 1900, int month = 1, - int day = 1, int hour = 0, int min = 0, int sec = 0, long ns = 0); - - /** - * Meta-programming class. - * Defines T1 as ::type if the condition is true, otherwise - * defines T2 as ::type. - */ - template - struct Conditional - { - typedef T1 type; - }; - - /** - * Specialization for the false case. - */ - template - struct Conditional - { - typedef T2 type; - }; - - /** - * Returns the bigger type. - */ - template - struct Bigger - { - typedef typename Conditional<(sizeof(T1) > sizeof(T2)), T1, T2>::type type; - }; - - /** - * Utility class to bind class instance with member function. - */ - template - class BoundInstance - { - public: - typedef R FunctionReturnType; - typedef T ClassType; - typedef FunctionReturnType(ClassType::* MemberFunctionType)(); - - /** - * Constructor. - * - * @param instance Class instance. - * @param mfunc Member function. - */ - BoundInstance(ClassType* instance, MemberFunctionType mfunc) : - instance(instance), - mfunc(mfunc) - { - // No-op. - } - - /** - * Invoke operator. - * - * @return Result of the invokation of the member function on the bound instance. - */ - FunctionReturnType operator()() - { - return (instance->*mfunc)(); - } - - private: - /** Instance reference. */ - ClassType* instance; - - /** Member function pointer. */ - MemberFunctionType mfunc; - }; - - /** - * Utility function for binding. - */ - template - BoundInstance Bind(T* instance, R(T::* mfunc)()) - { - return BoundInstance(instance, mfunc); - } - - /** - * Method guard class template. - * - * Upon destruction calls provided method on provided class instance. - * - * @tparam T Value type. - */ - template - class MethodGuard - { - public: - /** Value type. */ - typedef T ValueType; - - /** Mehtod type. */ - typedef void (ValueType::*MethodType)(); - - /** - * Constructor. - * - * @param val Instance, to call method on. - * @param method Method to call. - */ - MethodGuard(ValueType* val, MethodType method) : - val(val), - method(method) - { - // No-op. - } - - /** - * Destructor. - */ - ~MethodGuard() - { - if (val && method) - (val->*method)(); - } - - /** - * Release control over object. - */ - void Release() - { - val = 0; - method = 0; - } - - private: - /** Instance, to call method on. */ - ValueType* val; - - /** Method to call. */ - MethodType method; - }; - - /** - * Deinit guard class template. - * - * Upon destruction calls provided deinit function on provided instance. - * - * @tparam T Value type. - */ - template - class DeinitGuard - { - public: - /** Value type. */ - typedef T ValueType; - - /** Deinit function type. */ - typedef void (*FuncType)(ValueType*); - - /** - * Constructor. - * - * @param val Instance, to call method on. - * @param method Method to call. - */ - DeinitGuard(ValueType* val, FuncType method) : - val(val), - func(method) - { - // No-op. - } - - /** - * Destructor. - */ - ~DeinitGuard() - { - if (val && func) - (func)(val); - } - - /** - * Release control over object. - */ - void Release() - { - val = 0; - func = 0; - } - - private: - /** Instance, to call method on. */ - ValueType* val; - - /** Method to call. */ - FuncType func; - }; - - /** - * Get dynamic library full name. - * @param name Name without extension. - * @return Full name. - */ - IGNITE_IMPORT_EXPORT std::string GetDynamicLibraryName(const char* name); - } - } -} - -#endif //_IGNITE_ODBC_COMMON_UTILS diff --git a/src/odbc/include/ignite/odbc/connection.h b/src/odbc/include/ignite/odbc/connection.h index 0a917a50d..3fefc8e33 100644 --- a/src/odbc/include/ignite/odbc/connection.h +++ b/src/odbc/include/ignite/odbc/connection.h @@ -30,7 +30,7 @@ #include "ignite/odbc/diagnostic/diagnosable_adapter.h" #include "ignite/odbc/streaming/streaming_context.h" #include "ignite/odbc/odbc_error.h" -#include "ignite/odbc/jni/java.h" +#include "ignite/odbc/end_point.h" namespace ignite { @@ -228,6 +228,8 @@ namespace ignite if (!success) return false; + parser.Decode(rsp, tempBuffer); + return true; } @@ -487,23 +489,7 @@ namespace ignite * @throw IgniteError on failure. * @return @c true on success and @c false otherwise. */ - bool TryRestoreConnection(IgniteError& err); - - /** - * Formats the JDBC connection string from configuration values. - * @return the JDBC connection string. - */ - std::string FormatJdbcConnectionString() const; - - /** - * Creates JVM options - */ - void SetJvmOptions(const std::string& cp); - - /** - * De-initializes the JVM options - */ - void Deinit(); + bool TryRestoreConnection(); /** * Collect all addresses from config. @@ -529,6 +515,9 @@ namespace ignite /** Parent. */ Environment* env; + /** Client Socket. */ + std::auto_ptr socket; + /** Connection timeout in seconds. */ int32_t timeout; @@ -547,12 +536,6 @@ namespace ignite /** Connection info. */ config::ConnectionInfo info; - /** Java connection object */ - jobject connection; - - /** JVM options */ - std::vector< char* > opts; - /** Streaming context. */ streaming::StreamingContext streamingContext; }; diff --git a/src/odbc/include/ignite/odbc/ignite_error.h b/src/odbc/include/ignite/odbc/ignite_error.h deleted file mode 100644 index 5034a6e9c..000000000 --- a/src/odbc/include/ignite/odbc/ignite_error.h +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file - * Declares ignite::IgniteError class. - */ - -#ifndef _IGNITE_ODBC_IGNITE_ERROR -#define _IGNITE_ODBC_IGNITE_ERROR - -#include - -#include -#include - -#include - -#define IGNITE_ERROR_1(code, part1) { \ - std::stringstream stream; \ - stream << (part1); \ - throw ignite::IgniteError(code, stream.str().c_str()); \ -} - -#define IGNITE_ERROR_2(code, part1, part2) { \ - std::stringstream stream; \ - stream << (part1) << (part2); \ - throw ignite::IgniteError(code, stream.str().c_str()); \ -} - -#define IGNITE_ERROR_3(code, part1, part2, part3) { \ - std::stringstream stream; \ - stream << (part1) << (part2) << (part3); \ - throw ignite::IgniteError(code, stream.str().c_str()); \ -} - -#define IGNITE_ERROR_FORMATTED_1(code, msg, key1, val1) { \ - std::stringstream stream; \ - stream << msg << " [" << key1 << "=" << (val1) << "]"; \ - throw ignite::IgniteError(code, stream.str().c_str()); \ -} - -#define IGNITE_ERROR_FORMATTED_2(code, msg, key1, val1, key2, val2) { \ - std::stringstream stream; \ - stream << msg << " [" << key1 << "=" << (val1) << ", " << key2 << "=" << (val2) << "]"; \ - throw ignite::IgniteError(code, stream.str().c_str()); \ -} - -#define IGNITE_ERROR_FORMATTED_3(code, msg, key1, val1, key2, val2, key3, val3) { \ - std::stringstream stream; \ - stream << msg << " [" << key1 << "=" << (val1) << ", " << key2 << "=" << (val2) << ", " << key3 << "=" << (val3) << "]"; \ - throw ignite::IgniteError(code, stream.str().c_str()); \ -} - -#define IGNITE_ERROR_FORMATTED_4(code, msg, key1, val1, key2, val2, key3, val3, key4, val4) { \ - std::stringstream stream; \ - stream << msg << " [" << key1 << "=" << (val1) << ", " << key2 << "=" << (val2) << ", " << key3 << "=" << (val3) << ", " << key4 << "=" << (val4) << "]"; \ - throw ignite::IgniteError(code, stream.str().c_str()); \ -} - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable : 4275) -#endif //_MSC_VER - -namespace ignite -{ - namespace odbc - { - namespace java - { - /* JNI error constants. */ - const int IGNITE_JNI_ERR_SUCCESS = 0; - const int IGNITE_JNI_ERR_GENERIC = 1; - const int IGNITE_JNI_ERR_JVM_INIT = 2; - const int IGNITE_JNI_ERR_JVM_ATTACH = 3; - } - - /** - * %Ignite error information. - */ - class IGNITE_IMPORT_EXPORT IgniteError : public std::exception - { - public: - /** Success. */ - static const int IGNITE_SUCCESS = 0; - - /** Failed to initialize JVM. */ - static const int IGNITE_ERR_JVM_INIT = 1; - - /** Failed to attach to JVM. */ - static const int IGNITE_ERR_JVM_ATTACH = 2; - - /** JVM library is not found. */ - static const int IGNITE_ERR_JVM_LIB_NOT_FOUND = 3; - - /** Failed to load JVM library. */ - static const int IGNITE_ERR_JVM_LIB_LOAD_FAILED = 4; - - /** JVM classpath is not provided. */ - static const int IGNITE_ERR_JVM_NO_CLASSPATH = 5; - - /** JVM error: no class definition found. */ - static const int IGNITE_ERR_JVM_NO_CLASS_DEF_FOUND = 6; - - /** JVM error: no such method. */ - static const int IGNITE_ERR_JVM_NO_SUCH_METHOD = 7; - - /** Memory operation error. */ - static const int IGNITE_ERR_MEMORY = 1001; - - /** Binary error. */ - static const int IGNITE_ERR_BINARY = 1002; - - /** Standard library exception. */ - static const int IGNITE_ERR_STD = 1003; - - /** Generic %Ignite error. */ - static const int IGNITE_ERR_GENERIC = 2000; - - /** Illegal argument passed. */ - static const int IGNITE_ERR_ILLEGAL_ARGUMENT = 2001; - - /** Illegal state. */ - static const int IGNITE_ERR_ILLEGAL_STATE = 2002; - - /** Unsupported operation. */ - static const int IGNITE_ERR_UNSUPPORTED_OPERATION = 2003; - - /** Thread has been interrup. */ - static const int IGNITE_ERR_INTERRUPTED = 2004; - - /** Cluster group is empty. */ - static const int IGNITE_ERR_CLUSTER_GROUP_EMPTY = 2005; - - /** Cluster topology problem. */ - static const int IGNITE_ERR_CLUSTER_TOPOLOGY = 2006; - - /** Compute execution rejected. */ - static const int IGNITE_ERR_COMPUTE_EXECUTION_REJECTED = 2007; - - /** Compute job failover. */ - static const int IGNITE_ERR_COMPUTE_JOB_FAILOVER = 2008; - - /** Compute task cancelled. */ - static const int IGNITE_ERR_COMPUTE_TASK_CANCELLED = 2009; - - /** Compute task timeout. */ - static const int IGNITE_ERR_COMPUTE_TASK_TIMEOUT = 2010; - - /** Compute user undeclared exception. */ - static const int IGNITE_ERR_COMPUTE_USER_UNDECLARED_EXCEPTION = 2011; - - /** Generic cache error. */ - static const int IGNITE_ERR_CACHE = 2012; - - /** Generic cache loader error. */ - static const int IGNITE_ERR_CACHE_LOADER = 2013; - - /** Generic cache writer error. */ - static const int IGNITE_ERR_CACHE_WRITER = 2014; - - /** Generic cache entry processor error. */ - static const int IGNITE_ERR_ENTRY_PROCESSOR = 2015; - - /** Cache atomic update timeout. */ - static const int IGNITE_ERR_CACHE_ATOMIC_UPDATE_TIMEOUT = 2016; - - /** Cache partial update. */ - static const int IGNITE_ERR_CACHE_PARTIAL_UPDATE = 2017; - - /** Transaction optimisitc exception. */ - static const int IGNITE_ERR_TX_OPTIMISTIC = 2018; - - /** Transaction timeout. */ - static const int IGNITE_ERR_TX_TIMEOUT = 2019; - - /** Transaction rollback. */ - static const int IGNITE_ERR_TX_ROLLBACK = 2020; - - /** Transaction heuristic exception. */ - static const int IGNITE_ERR_TX_HEURISTIC = 2021; - - /** Authentication error. */ - static const int IGNITE_ERR_AUTHENTICATION = 2022; - - /** Security error. */ - static const int IGNITE_ERR_SECURITY = 2023; - - /** Future state error. */ - static const int IGNITE_ERR_FUTURE_STATE = 2024; - - /** Networking error. */ - static const int IGNITE_ERR_NETWORK_FAILURE = 2025; - - /** SSL/TLS error. */ - static const int IGNITE_ERR_SECURE_CONNECTION_FAILURE = 2026; - - /** Transaction already started by current thread. */ - static const int IGNITE_ERR_TX_THIS_THREAD = 2027; - - /** Generic transaction error. */ - static const int IGNITE_ERR_TX = 2028; - - - /** Unknown error. */ - static const int IGNITE_ERR_UNKNOWN = -1; - - /** - * Throw an error if code is not IGNITE_SUCCESS. - * - * @param err Error. - */ - static void ThrowIfNeeded(const IgniteError& err); - - /** - * Default constructor. - * Creates empty error. Code is IGNITE_SUCCESS and message is NULL. - */ - IgniteError(); - - /** - * Create error with specific code. Message is set to NULL. - * - * @param code Error code. - */ - IgniteError(const int32_t code); - - /** - * Create error with specific code and message. - * - * @param code Error code. - * @param msg Message. - */ - IgniteError(const int32_t code, const char* msg); - - /** - * Copy constructor. - * - * @param other Other instance. - */ - IgniteError(const IgniteError& other); - - /** - * Assignment operator. - * - * @param other Other instance. - * @return *this. - */ - IgniteError& operator=(const IgniteError& other); - - /** - * Destructor. - */ - ~IgniteError() IGNITE_NO_THROW; - - /** - * Get error code. - * - * @return Error code. - */ - int32_t GetCode() const; - - /** - * Get error message. - * - * @return Error message. Can be NULL. - */ - const char* GetText() const IGNITE_NO_THROW; - - /** - * Implementation of the standard std::exception::what() method. - * Synonym for GetText() method. - * - * @return Error message string. - */ - virtual const char* what() const IGNITE_NO_THROW; - - /** - * Initializes IgniteError instance from the JNI error. - * - * @param jniCode Error code. - * @param jniCls Error class. - * @param jniMsg Error message. - * @param err Error. Can not be NULL. - */ - static void SetError(const int jniCode, const char* jniCls, const char* jniMsg, IgniteError& err); - private: - /** Error code. */ - int32_t code; - - /** Error message. */ - char* msg; - }; - } -} - -#ifdef _MSC_VER -# pragma warning(pop) -#endif //_MSC_VER - -#endif //_IGNITE_ODBC_IGNITE_ERROR diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h deleted file mode 100644 index 3925aaf0a..000000000 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ /dev/null @@ -1,641 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _IGNITE_ODBC_JNI_JAVA -#define _IGNITE_ODBC_JNI_JAVA - -#include - -#include - -#include - -namespace ignite { - namespace odbc { - namespace jni { - namespace java { - - /* Handlers for callbacks from Java. */ - typedef int64_t(JNICALL* CacheStoreCreateHandler)(void* target, int64_t memPtr); - typedef int(JNICALL* CacheStoreInvokeHandler)(void* target, int64_t objPtr, - int64_t memPtr); - typedef void(JNICALL* CacheStoreDestroyHandler)(void* target, int64_t objPtr); - typedef int64_t(JNICALL* CacheStoreSessionCreateHandler)(void* target, - int64_t storePtr); - - typedef int64_t(JNICALL* CacheEntryFilterCreateHandler)(void* target, - int64_t memPtr); - typedef int(JNICALL* CacheEntryFilterApplyHandler)(void* target, int64_t ptr, - int64_t memPtr); - typedef void(JNICALL* CacheEntryFilterDestroyHandler)(void* target, - int64_t ptr); - - typedef void(JNICALL* CacheInvokeHandler)(void* target, int64_t inMemPtr, - int64_t outMemPtr); - - typedef void(JNICALL* ComputeTaskMapHandler)(void* target, int64_t taskPtr, - int64_t inMemPtr, - int64_t outMemPtr); - typedef int(JNICALL* ComputeTaskJobResultHandler)(void* target, int64_t taskPtr, - int64_t jobPtr, - int64_t memPtr); - typedef void(JNICALL* ComputeTaskReduceHandler)(void* target, int64_t taskPtr); - typedef void(JNICALL* ComputeTaskCompleteHandler)(void* target, int64_t taskPtr, - int64_t memPtr); - typedef int(JNICALL* ComputeJobSerializeHandler)(void* target, int64_t jobPtr, - int64_t memPtr); - typedef int64_t(JNICALL* ComputeJobCreateHandler)(void* target, int64_t memPtr); - typedef void(JNICALL* ComputeJobExecuteHandler)(void* target, int64_t jobPtr, - int cancel, int64_t memPtr); - typedef void(JNICALL* ComputeJobCancelHandler)(void* target, int64_t jobPtr); - typedef void(JNICALL* ComputeJobDestroyHandler)(void* target, int64_t jobPtr); - - typedef void(JNICALL* ContinuousQueryListenerApplyHandler)(void* target, - int64_t lsnrPtr, - int64_t memPtr); - typedef int64_t(JNICALL* ContinuousQueryFilterCreateHandler)(void* target, - int64_t memPtr); - typedef int(JNICALL* ContinuousQueryFilterApplyHandler)(void* target, - int64_t filterPtr, - int64_t memPtr); - typedef void(JNICALL* ContinuousQueryFilterReleaseHandler)(void* target, - int64_t filterPtr); - - typedef void(JNICALL* DataStreamerTopologyUpdateHandler)(void* target, - int64_t ldrPtr, - int64_t topVer, - int topSize); - typedef void(JNICALL* DataStreamerStreamReceiverInvokeHandler)( - void* target, int64_t ptr, void* cache, int64_t memPtr, - unsigned char keepPortable); - - typedef void(JNICALL* FutureByteResultHandler)(void* target, int64_t futAddr, - int res); - typedef void(JNICALL* FutureBoolResultHandler)(void* target, int64_t futAddr, - int res); - typedef void(JNICALL* FutureShortResultHandler)(void* target, int64_t futAddr, - int res); - typedef void(JNICALL* FutureCharResultHandler)(void* target, int64_t futAddr, - int res); - typedef void(JNICALL* FutureIntResultHandler)(void* target, int64_t futAddr, - int res); - typedef void(JNICALL* FutureFloatResultHandler)(void* target, int64_t futAddr, - float res); - typedef void(JNICALL* FutureLongResultHandler)(void* target, int64_t futAddr, - int64_t res); - typedef void(JNICALL* FutureDoubleResultHandler)(void* target, int64_t futAddr, - double res); - typedef void(JNICALL* FutureObjectResultHandler)(void* target, int64_t futAddr, - int64_t memPtr); - typedef void(JNICALL* FutureNullResultHandler)(void* target, int64_t futAddr); - typedef void(JNICALL* FutureErrorHandler)(void* target, int64_t futAddr, - int64_t memPtr); - - typedef void(JNICALL* LifecycleEventHandler)(void* target, int64_t ptr, - int evt); - - typedef void(JNICALL* MemoryReallocateHandler)(void* target, int64_t memPtr, - int cap); - - typedef int64_t(JNICALL* MessagingFilterCreateHandler)(void* target, - int64_t memPtr); - typedef int(JNICALL* MessagingFilterApplyHandler)(void* target, int64_t ptr, - int64_t memPtr); - typedef void(JNICALL* MessagingFilterDestroyHandler)(void* target, int64_t ptr); - - typedef int64_t(JNICALL* EventFilterCreateHandler)(void* target, - int64_t memPtr); - typedef int(JNICALL* EventFilterApplyHandler)(void* target, int64_t ptr, - int64_t memPtr); - typedef void(JNICALL* EventFilterDestroyHandler)(void* target, int64_t ptr); - - typedef int64_t(JNICALL* ServiceInitHandler)(void* target, int64_t memPtr); - typedef void(JNICALL* ServiceExecuteHandler)(void* target, int64_t svcPtr, - int64_t memPtr); - typedef void(JNICALL* ServiceCancelHandler)(void* target, int64_t svcPtr, - int64_t memPtr); - typedef void(JNICALL* ServiceInvokeMethodHandler)(void* target, int64_t svcPtr, - int64_t inMemPtr, - int64_t outMemPtr); - typedef int(JNICALL* ClusterNodeFilterApplyHandler)(void* target, - int64_t memPtr); - - typedef int64_t(JNICALL* NodeInfoHandler)(void* target, int64_t memPtr); - - typedef void(JNICALL* OnStartHandler)(void* target, void* proc, int64_t memPtr); - typedef void(JNICALL* OnStopHandler)(void* target); - typedef void(JNICALL* ErrorHandler)(void* target, int errCode, - const char* errClsChars, int errClsCharsLen, - const char* errMsgChars, int errMsgCharsLen, - const char* stackTraceChars, - int stackTraceCharsLen, void* errData, - int errDataLen); - - typedef int64_t(JNICALL* ExtensionCallbackInLongOutLongHandler)(void* target, - int typ, - int64_t arg1); - typedef int64_t(JNICALL* ExtensionCallbackInLongLongOutLongHandler)( - void* target, int typ, int64_t arg1, int64_t arg2); - - typedef void(JNICALL* OnClientDisconnectedHandler)(void* target); - typedef void(JNICALL* OnClientReconnectedHandler)( - void* target, unsigned char clusterRestarted); - - typedef int64_t(JNICALL* AffinityFunctionInitHandler)(void* target, - int64_t memPtr, - void* baseFunc); - typedef int(JNICALL* AffinityFunctionPartitionHandler)(void* target, - int64_t ptr, - int64_t memPtr); - typedef void(JNICALL* AffinityFunctionAssignPartitionsHandler)( - void* target, int64_t ptr, int64_t inMemPtr, int64_t outMemPtr); - typedef void(JNICALL* AffinityFunctionRemoveNodeHandler)(void* target, - int64_t ptr, - int64_t memPtr); - typedef void(JNICALL* AffinityFunctionDestroyHandler)(void* target, - int64_t ptr); - - typedef void(JNICALL* ConsoleWriteHandler)(const char* chars, int charsLen, - unsigned char isErr); - - typedef void(JNICALL* LoggerLogHandler)( - void* target, int level, const char* messageChars, int messageCharsLen, - const char* categoryChars, int categoryCharsLen, const char* errorInfoChars, - int errorInfoCharsLen, int64_t memPtr); - typedef bool(JNICALL* LoggerIsLevelEnabledHandler)(void* target, int level); - - typedef int64_t(JNICALL* InLongOutLongHandler)(void* target, int type, - int64_t val); - typedef int64_t(JNICALL* InLongLongLongObjectOutLongHandler)( - void* target, int type, int64_t val1, int64_t val2, int64_t val3, - void* arg); - - /** - * Is Java 9 or later is used. - * - * @return true if the Java 9 or later is in use. - */ - bool IGNITE_IMPORT_EXPORT IsJava9OrLater(); - - /** - * JNI handlers holder. - */ - struct JniHandlers { - void* target; - - ErrorHandler error; - - LoggerLogHandler loggerLog; - LoggerIsLevelEnabledHandler loggerIsLevelEnabled; - - InLongOutLongHandler inLongOutLong; - InLongLongLongObjectOutLongHandler inLongLongLongObjectOutLong; - }; - - /** - * JNI Java members. - */ - struct JniJavaMembers { - jclass c_Class; - jmethodID m_Class_getName; - - jclass c_Throwable; - jmethodID m_Throwable_getMessage; - jmethodID m_Throwable_printStackTrace; - - jclass c_PlatformUtils; - jmethodID m_PlatformUtils_getFullStackTrace; - - /** - * Constructor. - */ - void Initialize(JNIEnv* env); - - /** - * Destroy members releasing all allocated classes. - */ - void Destroy(JNIEnv* env); - - /** - * Write error information. - */ - bool WriteErrorInfo(JNIEnv* env, char** errClsName, int* errClsNameLen, - char** errMsg, int* errMsgLen, char** stackTrace, - int* stackTraceLen); - }; - - /** - * JNI members. - */ - struct JniMembers { - jclass c_DocumentDbConnectionProperties; - jmethodID m_DocumentDbConnectionPropertiesGetPropertiesFromConnectionString; - - jclass c_DocumentDbConnection; - jmethodID m_DocumentDbConnectionInit; - jmethodID m_DocumentDbClose; - - jclass c_DriverManager; - jmethodID m_DriverManagerGetConnection; - - jclass c_JavaSqlConnection; - jmethodID m_JavaSqlConnectionClose; - - jclass c_IgniteException; - - jclass c_PlatformIgnition; - jmethodID m_PlatformIgnition_start; - jmethodID m_PlatformIgnition_instance; - jmethodID m_PlatformIgnition_environmentPointer; - jmethodID m_PlatformIgnition_stop; - jmethodID m_PlatformIgnition_stopAll; - - jclass c_PlatformTarget; - jmethodID m_PlatformTarget_inLongOutLong; - jmethodID m_PlatformTarget_inStreamOutLong; - jmethodID m_PlatformTarget_inStreamOutObject; - jmethodID m_PlatformTarget_outStream; - jmethodID m_PlatformTarget_outObject; - jmethodID m_PlatformTarget_inStreamAsync; - jmethodID m_PlatformTarget_inStreamOutObjectAsync; - jmethodID m_PlatformTarget_inStreamOutStream; - jmethodID m_PlatformTarget_inObjectStreamOutObjectStream; - - jclass c_PlatformUtils; - jmethodID m_PlatformUtils_reallocate; - jmethodID m_PlatformUtils_errData; - - /** - * Constructor. - */ - void Initialize(JNIEnv* env); - - /** - * Destroy members releasing all allocated classes. - */ - void Destroy(JNIEnv* env); - }; - - /** - * JNI JVM wrapper. - */ - class IGNITE_IMPORT_EXPORT JniJvm { - public: - /** - * Default constructor for uninitialized JVM. - */ - JniJvm(); - - /** - * Constructor. - * - * @param jvm JVM. - * @param javaMembers Java members. - * @param members Members. - */ - JniJvm(JavaVM* jvm, JniJavaMembers javaMembers, JniMembers members); - - /** - * Get JVM. - * - * @param JVM. - */ - JavaVM* GetJvm(); - - /** - * Get Java members. - * - * @param Java members. - */ - JniJavaMembers& GetJavaMembers(); - - /** - * Get members. - * - * @param Members. - */ - JniMembers& GetMembers(); - - private: - /** JVM. */ - JavaVM* jvm; - - /** Java members. */ - JniJavaMembers javaMembers; - - /** Members. */ - JniMembers members; - }; - - /** - * JNI error information. - */ - struct IGNITE_IMPORT_EXPORT JniErrorInfo { - int code; - char* errCls = nullptr; - char* errMsg = nullptr; - - /** - * Default constructor. Creates empty error info. - */ - JniErrorInfo(); - - /** - * Constructor. - * - * @param code Code. - * @param errCls Error class. - * @param errMsg Error message. - */ - JniErrorInfo(int code, const char* errCls, const char* errMsg); - - /** - * Copy constructor. - * - * @param other Other instance. - */ - JniErrorInfo(const JniErrorInfo& other); - - /** - * Assignment operator overload. - * - * @param other Other instance. - * @return This instance. - */ - JniErrorInfo& operator=(const JniErrorInfo& other); - - /** - * Destructor. - */ - ~JniErrorInfo(); - }; - - /** - * Unmanaged context. - */ - class IGNITE_IMPORT_EXPORT JniContext { - public: - static JniContext* Create(char** opts, int optsLen, JniHandlers hnds); - static JniContext* Create(char** opts, int optsLen, JniHandlers hnds, - JniErrorInfo* errInfo); - static int Reallocate(int64_t memPtr, int cap); - static void Detach(); - static void Release(jobject obj); - static void SetConsoleHandler(ConsoleWriteHandler consoleHandler); - static int RemoveConsoleHandler(ConsoleWriteHandler consoleHandler); - - jobject DocumentDbConnect(const char* connectionString, - JniErrorInfo* errInfo); - - void DocumentDbDisconnect(const jobject connection, JniErrorInfo* errInfo); - - int64_t TargetInLongOutLong(jobject obj, int type, int64_t memPtr, - JniErrorInfo* errInfo = NULL); - int64_t TargetInStreamOutLong(jobject obj, int type, int64_t memPtr, - JniErrorInfo* errInfo = NULL); - void TargetInStreamOutStream(jobject obj, int opType, int64_t inMemPtr, - int64_t outMemPtr, - JniErrorInfo* errInfo = NULL); - jobject TargetInStreamOutObject(jobject obj, int type, int64_t memPtr, - JniErrorInfo* errInfo = NULL); - jobject TargetInObjectStreamOutObjectStream(jobject obj, int opType, - void* arg, int64_t inMemPtr, - int64_t outMemPtr, - JniErrorInfo* errInfo = NULL); - void TargetOutStream(jobject obj, int opType, int64_t memPtr, - JniErrorInfo* errInfo = NULL); - jobject TargetOutObject(jobject obj, int opType, - JniErrorInfo* errInfo = NULL); - void TargetInStreamAsync(jobject obj, int type, int64_t memPtr, - JniErrorInfo* errInfo = NULL); - jobject TargetInStreamOutObjectAsync(jobject obj, int type, int64_t memPtr, - JniErrorInfo* errInfo = NULL); - - jobject CacheOutOpQueryCursor(jobject obj, int type, int64_t memPtr, - JniErrorInfo* errInfo = NULL); - jobject CacheOutOpContinuousQuery(jobject obj, int type, int64_t memPtr, - JniErrorInfo* errInfo = NULL); - - jobject Acquire(jobject obj); - - void DestroyJvm(); - void ThrowToJava(char* errMsg); - - private: - JniJvm* jvm; - JniHandlers hnds; - - JniContext(JniJvm* jvm, JniHandlers hnds); - - JNIEnv* Attach(); - void ExceptionCheck(JNIEnv* env); - void ExceptionCheck(JNIEnv* env, JniErrorInfo* errInfo); - jobject LocalToGlobal(JNIEnv* env, jobject obj); - }; - - JNIEXPORT jlong JNICALL JniCacheStoreCreate(JNIEnv* env, jclass cls, - jlong envPtr, jlong memPtr); - JNIEXPORT jint JNICALL JniCacheStoreInvoke(JNIEnv* env, jclass cls, - jlong envPtr, jlong objPtr, - jlong memPtr); - JNIEXPORT void JNICALL JniCacheStoreDestroy(JNIEnv* env, jclass cls, - jlong envPtr, jlong objPtr); - JNIEXPORT jlong JNICALL JniCacheStoreSessionCreate(JNIEnv* env, jclass cls, - jlong envPtr, - jlong storePtr); - - JNIEXPORT jlong JNICALL JniCacheEntryFilterCreate(JNIEnv* env, jclass cls, - jlong envPtr, jlong memPtr); - JNIEXPORT jint JNICALL JniCacheEntryFilterApply(JNIEnv* env, jclass cls, - jlong envPtr, jlong objPtr, - jlong memPtr); - JNIEXPORT void JNICALL JniCacheEntryFilterDestroy(JNIEnv* env, jclass cls, - jlong envPtr, jlong objPtr); - - JNIEXPORT void JNICALL JniCacheInvoke(JNIEnv* env, jclass cls, jlong envPtr, - jlong inMemPtr, jlong outMemPtr); - - JNIEXPORT void JNICALL JniComputeTaskMap(JNIEnv* env, jclass cls, jlong envPtr, - jlong taskPtr, jlong inMemPtr, - jlong outMemPtr); - JNIEXPORT jint JNICALL JniComputeTaskJobResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong taskPtr, - jlong jobPtr, jlong memPtr); - JNIEXPORT void JNICALL JniComputeTaskReduce(JNIEnv* env, jclass cls, - jlong envPtr, jlong taskPtr); - JNIEXPORT void JNICALL JniComputeTaskComplete(JNIEnv* env, jclass cls, - jlong envPtr, jlong taskPtr, - jlong memPtr); - JNIEXPORT jint JNICALL JniComputeJobSerialize(JNIEnv* env, jclass cls, - jlong envPtr, jlong jobPtr, - jlong memPtr); - JNIEXPORT jlong JNICALL JniComputeJobCreate(JNIEnv* env, jclass cls, - jlong envPtr, jlong memPtr); - JNIEXPORT void JNICALL JniComputeJobExecute(JNIEnv* env, jclass cls, - jlong envPtr, jlong jobPtr, - jint cancel, jlong memPtr); - JNIEXPORT void JNICALL JniComputeJobCancel(JNIEnv* env, jclass cls, - jlong envPtr, jlong jobPtr); - JNIEXPORT void JNICALL JniComputeJobDestroy(JNIEnv* env, jclass cls, - jlong envPtr, jlong jobPtr); - - JNIEXPORT void JNICALL JniContinuousQueryListenerApply(JNIEnv* env, jclass cls, - jlong envPtr, - jlong cbPtr, - jlong memPtr); - JNIEXPORT jlong JNICALL JniContinuousQueryFilterCreate(JNIEnv* env, jclass cls, - jlong envPtr, - jlong memPtr); - JNIEXPORT jint JNICALL JniContinuousQueryFilterApply(JNIEnv* env, jclass cls, - jlong envPtr, - jlong filterPtr, - jlong memPtr); - JNIEXPORT void JNICALL JniContinuousQueryFilterRelease(JNIEnv* env, jclass cls, - jlong envPtr, - jlong filterPtr); - - JNIEXPORT void JNICALL JniDataStreamerTopologyUpdate(JNIEnv* env, jclass cls, - jlong envPtr, jlong ldrPtr, - jlong topVer, - jint topSize); - JNIEXPORT void JNICALL JniDataStreamerStreamReceiverInvoke( - JNIEnv* env, jclass cls, jlong envPtr, jlong ptr, jobject cache, - jlong memPtr, jboolean keepPortable); - - JNIEXPORT void JNICALL JniFutureByteResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong futPtr, - jint res); - JNIEXPORT void JNICALL JniFutureBoolResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong futPtr, - jint res); - JNIEXPORT void JNICALL JniFutureShortResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong futPtr, - jint res); - JNIEXPORT void JNICALL JniFutureCharResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong futPtr, - jint res); - JNIEXPORT void JNICALL JniFutureIntResult(JNIEnv* env, jclass cls, jlong envPtr, - jlong futPtr, jint res); - JNIEXPORT void JNICALL JniFutureFloatResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong futPtr, - jfloat res); - JNIEXPORT void JNICALL JniFutureLongResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong futPtr, - jlong res); - JNIEXPORT void JNICALL JniFutureDoubleResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong futPtr, - jdouble res); - JNIEXPORT void JNICALL JniFutureObjectResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong futPtr, - jlong memPtr); - JNIEXPORT void JNICALL JniFutureNullResult(JNIEnv* env, jclass cls, - jlong envPtr, jlong futPtr); - JNIEXPORT void JNICALL JniFutureError(JNIEnv* env, jclass cls, jlong envPtr, - jlong futPtr, jlong memPtr); - - JNIEXPORT void JNICALL JniLifecycleEvent(JNIEnv* env, jclass cls, jlong envPtr, - jlong ptr, jint evt); - - JNIEXPORT void JNICALL JniMemoryReallocate(JNIEnv* env, jclass cls, - jlong envPtr, jlong memPtr, - jint cap); - - JNIEXPORT jlong JNICALL JniMessagingFilterCreate(JNIEnv* env, jclass cls, - jlong envPtr, jlong memPtr); - JNIEXPORT jint JNICALL JniMessagingFilterApply(JNIEnv* env, jclass cls, - jlong envPtr, jlong ptr, - jlong memPtr); - JNIEXPORT void JNICALL JniMessagingFilterDestroy(JNIEnv* env, jclass cls, - jlong envPtr, jlong ptr); - - JNIEXPORT jlong JNICALL JniEventFilterCreate(JNIEnv* env, jclass cls, - jlong envPtr, jlong memPtr); - JNIEXPORT jint JNICALL JniEventFilterApply(JNIEnv* env, jclass cls, - jlong envPtr, jlong ptr, - jlong memPtr); - JNIEXPORT void JNICALL JniEventFilterDestroy(JNIEnv* env, jclass cls, - jlong envPtr, jlong ptr); - - JNIEXPORT jlong JNICALL JniServiceInit(JNIEnv* env, jclass cls, jlong envPtr, - jlong memPtr); - JNIEXPORT void JNICALL JniServiceExecute(JNIEnv* env, jclass cls, jlong envPtr, - jlong svcPtr, jlong memPtr); - JNIEXPORT void JNICALL JniServiceCancel(JNIEnv* env, jclass cls, jlong envPtr, - jlong svcPtr, jlong memPtr); - JNIEXPORT void JNICALL JniServiceInvokeMethod(JNIEnv* env, jclass cls, - jlong envPtr, jlong svcPtr, - jlong inMemPtr, jlong outMemPtr); - JNIEXPORT jint JNICALL JniClusterNodeFilterApply(JNIEnv* env, jclass cls, - jlong envPtr, jlong memPtr); - - JNIEXPORT jlong JNICALL JniNodeInfo(JNIEnv* env, jclass cls, jlong envPtr, - jlong memPtr); - - JNIEXPORT void JNICALL JniOnStart(JNIEnv* env, jclass cls, jlong envPtr, - jobject proc, jlong memPtr); - JNIEXPORT void JNICALL JniOnStop(JNIEnv* env, jclass cls, jlong envPtr); - - JNIEXPORT jlong JNICALL JniExtensionCallbackInLongOutLong(JNIEnv* env, - jclass cls, - jlong envPtr, - jint typ, jlong arg1); - JNIEXPORT jlong JNICALL JniExtensionCallbackInLongLongOutLong( - JNIEnv* env, jclass cls, jlong envPtr, jint typ, jlong arg1, jlong arg2); - - JNIEXPORT void JNICALL JniOnClientDisconnected(JNIEnv* env, jclass cls, - jlong envPtr); - JNIEXPORT void JNICALL JniOnClientReconnected(JNIEnv* env, jclass cls, - jlong envPtr, - jboolean clusterRestarted); - - JNIEXPORT jlong JNICALL JniAffinityFunctionInit(JNIEnv* env, jclass cls, - jlong envPtr, jlong memPtr, - jobject baseFunc); - JNIEXPORT jint JNICALL JniAffinityFunctionPartition(JNIEnv* env, jclass cls, - jlong envPtr, jlong ptr, - jlong memPtr); - JNIEXPORT void JNICALL - JniAffinityFunctionAssignPartitions(JNIEnv* env, jclass cls, jlong envPtr, - jlong ptr, jlong inMemPtr, jlong outMemPtr); - JNIEXPORT void JNICALL JniAffinityFunctionRemoveNode(JNIEnv* env, jclass cls, - jlong envPtr, jlong ptr, - jlong memPtr); - JNIEXPORT void JNICALL JniAffinityFunctionDestroy(JNIEnv* env, jclass cls, - jlong envPtr, jlong ptr); - - JNIEXPORT void JNICALL JniConsoleWrite(JNIEnv* env, jclass cls, jstring str, - jboolean isErr); - - JNIEXPORT void JNICALL JniLoggerLog(JNIEnv* env, jclass cls, jlong envPtr, - jint level, jstring message, - jstring category, jstring errorInfo, - jlong memPtr); - JNIEXPORT jboolean JNICALL JniLoggerIsLevelEnabled(JNIEnv* env, jclass cls, - jlong envPtr, jint level); - - JNIEXPORT jlong JNICALL JniInLongOutLong(JNIEnv* env, jclass cls, jlong envPtr, - jint type, jlong val); - JNIEXPORT jlong JNICALL JniInLongLongLongObjectOutLong(JNIEnv* env, jclass cls, - jlong envPtr, jint type, - jlong val1, jlong val2, - jlong val3, jobject arg); - } // namespace java - } // namespace jni - } // namespace odbc -} // namespace ignite - -#endif //_IGNITE_ODBC_JNI_JAVA diff --git a/src/odbc/include/ignite/odbc/jni/utils.h b/src/odbc/include/ignite/odbc/jni/utils.h deleted file mode 100644 index 508a40756..000000000 --- a/src/odbc/include/ignite/odbc/jni/utils.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _IGNITE_ODBC_JNI_UTILS -#define _IGNITE_ODBC_JNI_UTILS - -#include - -#include -#include -#include - -namespace ignite -{ - namespace odbc - { - namespace jni - { - /** - * Helper class to manage attached threads. - */ - class AttachHelper - { - public: - /** - * Destructor. - */ - ~AttachHelper(); - - /** - * Callback invoked on successful thread attach ot JVM. - */ - static void OnThreadAttach(); - }; - - /** - * Represents global reference to Java object. - */ - class IGNITE_IMPORT_EXPORT JavaGlobalRef - { - public: - /** - * Default constructor - */ - JavaGlobalRef() : - obj(NULL) - { - // No-op. - } - - /** - * Constructor - * - * @param ctx JNI context. - * @param obj Java object. - */ - JavaGlobalRef(common::concurrent::SharedPointer& ctx, jobject obj) - : obj(NULL) - { - Init(ctx, obj); - } - - /** - * Copy constructor - * - * @param other Other instance. - */ - JavaGlobalRef(const JavaGlobalRef& other) - : obj(NULL) - { - Init(other.ctx, other.obj); - } - - /** - * Assignment operator. - * - * @param other Other instance. - * @return *this. - */ - JavaGlobalRef& operator=(const JavaGlobalRef& other) - { - if (this != &other) - { - java::JniContext::Release(obj); - - Init(other.ctx, other.obj); - } - - return *this; - } - - /** - * Destructor. - */ - ~JavaGlobalRef() - { - java::JniContext::Release(obj); - } - - /** - * Get object. - * - * @return Object. - */ - jobject Get() - { - return obj; - } - - private: - /** Initializer */ - void Init(const common::concurrent::SharedPointer& ctx0, jobject obj0) { - ctx = ctx0; - - if (ctx.IsValid()) - this->obj = ctx.Get()->Acquire(obj0); - } - - /** Context. */ - common::concurrent::SharedPointer ctx; - - /** Object. */ - jobject obj; - }; - - /** - * Attempts to find JVM library to load it into the process later. - * First search is performed using the passed path argument (is not NULL). - * Then JRE_HOME is evaluated. Last, JAVA_HOME is evaluated. - * - * @param path Explicitly defined path (optional). - * @return Path to the file. Empty string if the library was not found. - */ - IGNITE_IMPORT_EXPORT std::string FindJvmLibrary(const std::string& path); - - /** - * Load JVM library into the process. - * - * @param path Optional path to the library. - * @return Whether load was successful. - */ - IGNITE_IMPORT_EXPORT bool LoadJvmLibrary(const std::string& path); - - /** - * Helper function to create classpath based on Ignite home directory. - * - * @param home Home directory; expected to be valid. - * @param forceTest Force test classpath. - * @return Classpath. - */ - IGNITE_IMPORT_EXPORT std::string CreateDocumentDbHomeClasspath(const std::string& home, bool forceTest); - - /** - * Create Ignite classpath based on user input and home directory. - * - * @param usrCp User's classpath. - * @param home Ignite home directory. - * @return Classpath. - */ - IGNITE_IMPORT_EXPORT std::string CreateDocumentDbClasspath(const std::string& usrCp, const std::string& home); - - /** - * Resolve DOCUMENTDB_HOME directory. Resolution is performed in several - * steps: - * 1) Check for path provided as argument. - * 2) Check for environment variable. - * 3) Check for current working directory. - * Result of these checks are evaluated based on existence of certain - * predefined folders inside possible Ignite home. If they are found, - * IGNITE_HOME is considered resolved. - * - * @param path Optional path to evaluate. - * @return Resolved Ignite home. - */ - IGNITE_IMPORT_EXPORT std::string ResolveDocumentDbHome(const std::string& path = ""); - } - } -} - -#endif //_IGNITE_ODBC_JNI_UTILS diff --git a/src/odbc/include/ignite/odbc/log.h b/src/odbc/include/ignite/odbc/log.h index 2e361ea20..5a6dafcb9 100644 --- a/src/odbc/include/ignite/odbc/log.h +++ b/src/odbc/include/ignite/odbc/log.h @@ -22,8 +22,8 @@ #include #include -#include "ignite/odbc/common/common.h" -#include "ignite/odbc/common/concurrent.h" +#include "ignite/common/common.h" +#include "ignite/common/concurrent.h" # define LOG_MSG(param) \ if (ignite::odbc::Logger* p = ignite::odbc::Logger::Get()) \ @@ -112,7 +112,7 @@ namespace ignite IGNITE_NO_COPY_ASSIGNMENT(Logger); /** Mutex for writes synchronization. */ - odbc::common::concurrent::CriticalSection mutex; + ignite::common::concurrent::CriticalSection mutex; /** File stream. */ std::ofstream stream; diff --git a/src/odbc/include/ignite/odbc/meta/column_meta.h b/src/odbc/include/ignite/odbc/meta/column_meta.h index d38ed2b9c..5144fa3b8 100644 --- a/src/odbc/include/ignite/odbc/meta/column_meta.h +++ b/src/odbc/include/ignite/odbc/meta/column_meta.h @@ -75,7 +75,7 @@ namespace ignite /** * Default constructor. */ - ColumnMeta() : dataType(), nullability(), precision(), scale() + ColumnMeta() { // No-op. } diff --git a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h index 1cb69f741..a2f531863 100644 --- a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h +++ b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h @@ -40,7 +40,7 @@ namespace ignite /** * Default constructor. */ - PrimaryKeyMeta() : keySeq(0) + PrimaryKeyMeta() { // No-op. } diff --git a/src/odbc/include/ignite/odbc/odbc_error.h b/src/odbc/include/ignite/odbc/odbc_error.h index 07664329d..9b3b48d4f 100644 --- a/src/odbc/include/ignite/odbc/odbc_error.h +++ b/src/odbc/include/ignite/odbc/odbc_error.h @@ -21,7 +21,7 @@ #include #include -#include +#include namespace ignite { @@ -102,13 +102,13 @@ namespace ignite std::string errMessage; }; - typedef odbc::common::Unexpected OdbcUnexpected; + typedef common::Unexpected OdbcUnexpected; /** * Expected specialization for OdbcError. */ template - struct OdbcExpected : odbc::common::Expected + struct OdbcExpected : common::Expected { OdbcExpected(const R& res) : common::Expected(res) diff --git a/src/odbc/include/ignite/odbc/utility.h b/src/odbc/include/ignite/odbc/utility.h index cf31de0d6..152da6635 100644 --- a/src/odbc/include/ignite/odbc/utility.h +++ b/src/odbc/include/ignite/odbc/utility.h @@ -26,8 +26,8 @@ #include -#include -#include +#include +#include #include "ignite/impl/binary/binary_reader_impl.h" #include "ignite/impl/binary/binary_writer_impl.h" @@ -83,7 +83,7 @@ namespace ignite * @param reader Reader. * @param decimal Decimal value. */ - void ReadDecimal(impl::binary::BinaryReaderImpl& reader, odbc::common::Decimal& decimal); + void ReadDecimal(impl::binary::BinaryReaderImpl& reader, common::Decimal& decimal); /** * Write decimal value using writer. @@ -91,7 +91,7 @@ namespace ignite * @param writer Writer. * @param decimal Decimal value. */ - void WriteDecimal(impl::binary::BinaryWriterImpl& writer, const odbc::common::Decimal& decimal); + void WriteDecimal(impl::binary::BinaryWriterImpl& writer, const common::Decimal& decimal); /** * Convert SQL string buffer to std::string. diff --git a/src/odbc/install/install_amd64.cmd b/src/odbc/install/install_amd64.cmd index 5795e0cf8..6c7de9393 100644 --- a/src/odbc/install/install_amd64.cmd +++ b/src/odbc/install/install_amd64.cmd @@ -29,7 +29,7 @@ if exist %ODBC_AMD64% ( if [%ODBC_X86%] == [] ( echo warning: 32-bit driver is not specified. If you want to install 32-bit driver please specify path to it as a second argument. pause - exit /b 0 + exit /b 1 ) if exist %ODBC_X86% ( @@ -44,6 +44,5 @@ if exist %ODBC_X86% ( reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ODBC\ODBCINST.INI\ODBC Drivers" /v "Apache Ignite" /t REG_SZ /d "Installed" /f ) else ( echo warning: 32-bit driver can not be found: %ODBC_X86% - exit /b 1 ) diff --git a/src/odbc/os/linux/include/ignite/odbc/common/common.h b/src/odbc/os/linux/include/ignite/odbc/common/common.h deleted file mode 100644 index 5e3924c3a..000000000 --- a/src/odbc/os/linux/include/ignite/odbc/common/common.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _IGNITE_ODBC_COMMON_COMMON -#define _IGNITE_ODBC_COMMON_COMMON - -#ifndef __has_attribute -# define __has_attribute(x) 0 -#endif - -#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility) -# define IGNITE_EXPORT __attribute__((visibility("default"))) -# define IGNITE_IMPORT __attribute__((visibility("default"))) -#else -# define IGNITE_EXPORT -# define IGNITE_IMPORT -#endif - -#define IGNITE_CALL - -#ifdef IGNITE_IMPL -# define IGNITE_IMPORT_EXPORT IGNITE_EXPORT -#else -# define IGNITE_IMPORT_EXPORT IGNITE_IMPORT -#endif - -#if (__cplusplus >= 201103L) -# define IGNITE_NO_THROW noexcept -#else -# define IGNITE_NO_THROW throw() -#endif - -#define IGNITE_UNUSED(x) ((void) x) - -/** - * Common construction to disable copy constructor and assignment for class. - */ -#define IGNITE_NO_COPY_ASSIGNMENT(cls) \ - cls(const cls& src); \ - cls& operator= (const cls& other) - -#endif //_IGNITE_ODBC_COMMON_COMMON diff --git a/src/odbc/os/linux/include/ignite/odbc/common/concurrent_os.h b/src/odbc/os/linux/include/ignite/odbc/common/concurrent_os.h deleted file mode 100644 index 74711337b..000000000 --- a/src/odbc/os/linux/include/ignite/odbc/common/concurrent_os.h +++ /dev/null @@ -1,701 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _IGNITE_ODBC_COMMON_CONCURRENT_OS -#define _IGNITE_ODBC_COMMON_CONCURRENT_OS - -#include -#include -#include - -#include - -#include -#include - -#include - -namespace ignite -{ - namespace odbc - { - namespace common - { - namespace concurrent - { - /** - * Static class to manage memory visibility semantics. - */ - class IGNITE_IMPORT_EXPORT Memory { - public: - /** - * Full fence. - */ - static void Fence(); - }; - - /** - * Critical section. - */ - class IGNITE_IMPORT_EXPORT CriticalSection - { - friend class ConditionVariable; - public: - /** - * Constructor. - */ - CriticalSection(); - - /** - * Destructor. - */ - ~CriticalSection(); - - /** - * Enter critical section. - */ - void Enter(); - - /** - * Leave critical section. - */ - void Leave(); - private: - pthread_mutex_t mux; - - IGNITE_NO_COPY_ASSIGNMENT(CriticalSection); - }; - - class IGNITE_IMPORT_EXPORT ReadWriteLock - { - public: - /** - * Constructor. - */ - ReadWriteLock(); - - /** - * Destructor. - */ - ~ReadWriteLock(); - - /** - * Lock in exclusive mode. - */ - void LockExclusive(); - - /** - * Release in exclusive mode. - */ - void ReleaseExclusive(); - - /** - * Lock in shared mode. - */ - void LockShared(); - - /** - * Release in shared mode. - */ - void ReleaseShared(); - - private: - /** Lock. */ - pthread_rwlock_t lock; - - IGNITE_NO_COPY_ASSIGNMENT(ReadWriteLock); - }; - - /** - * Special latch with count = 1. - */ - class IGNITE_IMPORT_EXPORT SingleLatch - { - public: - /** - * Constructor. - */ - SingleLatch(); - - /** - * Destructor. - */ - ~SingleLatch(); - - /** - * Perform the countdown. - */ - void CountDown(); - - /** - * Await the countdown. - */ - void Await(); - private: - /** Mutex. */ - pthread_mutex_t mux; - - /** Condition. */ - pthread_cond_t cond; - - /** Ready flag. */ - bool ready; - - IGNITE_NO_COPY_ASSIGNMENT(SingleLatch); - }; - - /** - * Primitives for atomic access. - */ - class IGNITE_IMPORT_EXPORT Atomics - { - public: - /** - * Update the 32-bit integer value if it is equal to expected value. - * - * @param ptr Pointer. - * @param expVal Expected value. - * @param newVal New value. - * @return True if update occurred as a result of this call, false otherwise. - */ - static bool CompareAndSet32(int32_t* ptr, int32_t expVal, int32_t newVal); - - /** - * Update the 32-bit integer value if it is equal to expected value. - * - * @param ptr Pointer. - * @param expVal Expected value. - * @param newVal New value. - * @return Value which were observed during CAS attempt. - */ - static int32_t CompareAndSet32Val(int32_t* ptr, int32_t expVal, int32_t newVal); - - /** - * Increment 32-bit integer and return new value. - * - * @param ptr Pointer. - * @return Value after increment. - */ - static int32_t IncrementAndGet32(int32_t* ptr); - - /** - * Decrement 32-bit integer and return new value. - * - * @param ptr Pointer. - * @return Value after decrement. - */ - static int32_t DecrementAndGet32(int32_t* ptr); - - /** - * Update the 64-bit integer value if it is equal to expected value. - * - * @param ptr Pointer. - * @param expVal Expected value. - * @param newVal New value. - * @return True if update occurred as a result of this call, false otherwise. - */ - static bool CompareAndSet64(int64_t* ptr, int64_t expVal, int64_t newVal); - - /** - * Update the 64-bit integer value if it is equal to expected value. - * - * @param ptr Pointer. - * @param expVal Expected value. - * @param newVal New value. - * @return Value which were observed during CAS attempt. - */ - static int64_t CompareAndSet64Val(int64_t* ptr, int64_t expVal, int64_t newVal); - - /** - * Increment 64-bit integer and return new value. - * - * @param ptr Pointer. - * @return Value after increment. - */ - static int64_t IncrementAndGet64(int64_t* ptr); - - /** - * Decrement 64-bit integer and return new value. - * - * @param ptr Pointer. - * @return Value after decrement. - */ - static int64_t DecrementAndGet64(int64_t* ptr); - }; - - /** - * Thread-local entry. - */ - class IGNITE_IMPORT_EXPORT ThreadLocalEntry - { - public: - /** - * Virtual destructor to allow for correct typed entries cleanup. - */ - virtual ~ThreadLocalEntry() - { - // No-op. - } - }; - - /** - * Typed thread-local entry. - */ - template - class IGNITE_IMPORT_EXPORT ThreadLocalTypedEntry : public ThreadLocalEntry - { - public: - /** - * Constructor. - * - * @param val Value. - */ - ThreadLocalTypedEntry(T val) : val(val) - { - // No-op. - } - - ~ThreadLocalTypedEntry() - { - // No-op. - } - - /** - * Get value. - * - * @return Value. - */ - T Get() - { - return val; - } - private: - /** Value. */ - T val; - }; - - /** - * Thread-local abstraction. - */ - class IGNITE_IMPORT_EXPORT ThreadLocal - { - public: - /** - * Get next available index to be used in thread-local storage. - * - * @return Index. - */ - static int32_t NextIndex(); - - /** - * Get value by index. - * - * @param idx Index. - * @return Value associated with the index or NULL. - */ - template - static T Get(int32_t idx) - { - void* linuxVal = Get0(); - - if (linuxVal) - { - std::map* map = - static_cast*>(linuxVal); - - ThreadLocalTypedEntry* entry = static_cast*>((*map)[idx]); - - if (entry) - return entry->Get(); - } - - return T(); - } - - /** - * Set value at the given index. - * - * @param idx Index. - * @param val Value to be associated with the index. - */ - template - static void Set(int32_t idx, const T& val) - { - void* linuxVal = Get0(); - - if (linuxVal) - { - std::map* map = - static_cast*>(linuxVal); - - ThreadLocalEntry* appVal = (*map)[idx]; - - if (appVal) - delete appVal; - - (*map)[idx] = new ThreadLocalTypedEntry(val); - } - else - { - std::map* map = new std::map(); - - Set0(map); - - (*map)[idx] = new ThreadLocalTypedEntry(val); - } - } - - /** - * Remove value at the given index. - * - * @param idx Index. - */ - static void Remove(int32_t idx); - - /** - * Internal thread-local map clear routine. - * - * @param mapPtr Pointer to map. - */ - static void Clear0(void* mapPtr); - - private: - /** - * Internal get routine. - * - * @param Associated value. - */ - static void* Get0(); - - /** - * Internal set routine. - * - * @param ptr Pointer. - */ - static void Set0(void* ptr); - }; - - /** - * Thread-local instance. Simplifies API avoiding direct index allocations. - */ - template - class IGNITE_IMPORT_EXPORT ThreadLocalInstance - { - public: - /** - * Constructor. - */ - ThreadLocalInstance() : idx(ThreadLocal::NextIndex()) - { - // No-op. - } - - /** - * Destructor. - */ - ~ThreadLocalInstance() - { - Remove(); - } - - /** - * Get value. - * - * @return Value. - */ - T Get() - { - return ThreadLocal::Get(idx); - } - - /** - * Set instance. - * - * @param val Value. - */ - void Set(const T& val) - { - ThreadLocal::Set(idx, val); - } - - /** - * Remove instance. - */ - void Remove() - { - ThreadLocal::Remove(idx); - } - - private: - /** Index. */ - int32_t idx; - }; - - /** - * Cross-platform wrapper for Condition Variable synchronization - * primitive concept. - */ - class ConditionVariable - { - public: - /** - * Constructor. - */ - ConditionVariable() - { - pthread_condattr_t attr; - int err = pthread_condattr_init(&attr); - assert(!err); - IGNITE_UNUSED(err); - - #if !defined(__APPLE__) - err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); - assert(!err); - IGNITE_UNUSED(err); - #endif - err = pthread_cond_init(&cond, &attr); - assert(!err); - IGNITE_UNUSED(err); - } - - /** - * Destructor. - */ - ~ConditionVariable() - { - pthread_cond_destroy(&cond); - } - - /** - * Wait for Condition Variable to be notified. - * - * @param cs Critical section in which to wait. - */ - void Wait(CriticalSection& cs) - { - pthread_cond_wait(&cond, &cs.mux); - } - - /** - * Wait for Condition Variable to be notified for specified time. - * - * @param cs Critical section in which to wait. - * @param msTimeout Timeout in milliseconds. - * @return True if the object has been notified and false in case of timeout. - */ - bool WaitFor(CriticalSection& cs, int32_t msTimeout) - { - timespec ts; - int err = clock_gettime(CLOCK_MONOTONIC, &ts); - assert(!err); - - IGNITE_UNUSED(err); - - ts.tv_sec += msTimeout / 1000 + (ts.tv_nsec + (msTimeout % 1000) * 1000000) / 1000000000; - ts.tv_nsec = (ts.tv_nsec + (msTimeout % 1000) * 1000000) % 1000000000; - - int res = pthread_cond_timedwait(&cond, &cs.mux, &ts); - - return res == 0; - } - - /** - * Notify single thread waiting for the condition variable. - */ - void NotifyOne() - { - int err = pthread_cond_signal(&cond); - - assert(!err); - - IGNITE_UNUSED(err); - } - - /** - * Notify all threads that are waiting on the variable. - */ - void NotifyAll() - { - int err = pthread_cond_broadcast(&cond); - - assert(!err); - - IGNITE_UNUSED(err); - } - - private: - IGNITE_NO_COPY_ASSIGNMENT(ConditionVariable); - - /** OS-specific type. */ - pthread_cond_t cond; - }; - - /** - * Manually triggered event. - * Once triggered it stays in passing state until manually reset. - */ - class ManualEvent - { - public: - /** - * Constructs manual event. - * Initial state is untriggered. - */ - ManualEvent() : - cond(), - mutex(), - state(false) - { - pthread_condattr_t attr; - int err = pthread_condattr_init(&attr); - assert(!err); - IGNITE_UNUSED(err); - - #if !defined(__APPLE__) - err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); - assert(!err); - IGNITE_UNUSED(err); - #endif - - err = pthread_cond_init(&cond, &attr); - assert(!err); - IGNITE_UNUSED(err); - - err = pthread_mutex_init(&mutex, NULL); - assert(!err); - IGNITE_UNUSED(err); - } - - /** - * Destructor. - */ - ~ManualEvent() - { - pthread_mutex_destroy(&mutex); - pthread_cond_destroy(&cond); - } - - /** - * Sets event into triggered state. - */ - void Set() - { - int err = pthread_mutex_lock(&mutex); - assert(!err); - IGNITE_UNUSED(err); - - state = true; - - err = pthread_cond_broadcast(&cond); - assert(!err); - IGNITE_UNUSED(err); - - err = pthread_mutex_unlock(&mutex); - assert(!err); - IGNITE_UNUSED(err); - } - - /** - * Resets event into non-triggered state. - */ - void Reset() - { - int err = pthread_mutex_lock(&mutex); - assert(!err); - IGNITE_UNUSED(err); - - state = false; - - err = pthread_mutex_unlock(&mutex); - assert(!err); - IGNITE_UNUSED(err); - } - - /** - * Wait for event to be triggered. - */ - void Wait() - { - int err = pthread_mutex_lock(&mutex); - assert(!err); - IGNITE_UNUSED(err); - - while (!state) - { - err = pthread_cond_wait(&cond, &mutex); - assert(!err); - IGNITE_UNUSED(err); - } - - err = pthread_mutex_unlock(&mutex); - assert(!err); - IGNITE_UNUSED(err); - } - - /** - * Wait for event to be triggered for specified time. - * - * @param msTimeout Timeout in milliseconds. - * @return True if the object has been triggered and false in case of timeout. - */ - bool WaitFor(int32_t msTimeout) - { - int res = 0; - int err = pthread_mutex_lock(&mutex); - assert(!err); - IGNITE_UNUSED(err); - - if (!state) - { - timespec ts; - err = clock_gettime(CLOCK_MONOTONIC, &ts); - assert(!err); - IGNITE_UNUSED(err); - - ts.tv_sec += msTimeout / 1000 + (ts.tv_nsec + (msTimeout % 1000) * 1000000) / 1000000000; - ts.tv_nsec = (ts.tv_nsec + (msTimeout % 1000) * 1000000) % 1000000000; - - res = pthread_cond_timedwait(&cond, &mutex, &ts); - assert(res == 0 || res == ETIMEDOUT); - IGNITE_UNUSED(res); - } - - err = pthread_mutex_unlock(&mutex); - assert(!err); - IGNITE_UNUSED(err); - - return res == 0; - } - - private: - IGNITE_NO_COPY_ASSIGNMENT(ManualEvent); - - /** Condition variable. */ - pthread_cond_t cond; - - /** Mutex. */ - pthread_mutex_t mutex; - - /** State. */ - bool state; - }; - } - } - } -} - -#endif // _IGNITE_ODBC_COMMON_CONCURRENT_OS diff --git a/src/odbc/os/linux/src/common/concurrent_os.cpp b/src/odbc/os/linux/src/common/concurrent_os.cpp deleted file mode 100644 index aa04e55c9..000000000 --- a/src/odbc/os/linux/src/common/concurrent_os.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ignite/odbc/common/concurrent_os.h" - -namespace ignite -{ - namespace odbc - { - namespace common - { - namespace concurrent - { - /** Key indicating that the thread is attached. */ - static pthread_key_t tlsKey; - - /** Helper to ensure that attach key is allocated only once. */ - static pthread_once_t tlsKeyInit = PTHREAD_ONCE_INIT; - - /** - * Routine to destroy TLS key. - * - * @param key Key. - */ - void DestroyTlsKey(void* key) { - ThreadLocal::Clear0(key); - } - - /** - * Routine to allocate TLS key. - */ - void AllocateTlsKey() { - pthread_key_create(&tlsKey, DestroyTlsKey); - } - - void Memory::Fence() { - __asm__ volatile ("" ::: "memory"); - } - - CriticalSection::CriticalSection() { - pthread_mutex_init(&mux, NULL); - - Memory::Fence(); - } - - CriticalSection::~CriticalSection() { - Memory::Fence(); - - pthread_mutex_destroy(&mux); - } - - void CriticalSection::Enter() { - Memory::Fence(); - - pthread_mutex_lock(&mux); - } - - void CriticalSection::Leave() { - Memory::Fence(); - - pthread_mutex_unlock(&mux); - } - - ReadWriteLock::ReadWriteLock() : - lock() - { - pthread_rwlock_init(&lock, NULL); - - Memory::Fence(); - } - - ReadWriteLock::~ReadWriteLock() - { - pthread_rwlock_destroy(&lock); - } - - void ReadWriteLock::LockExclusive() - { - pthread_rwlock_wrlock(&lock); - } - - void ReadWriteLock::ReleaseExclusive() - { - pthread_rwlock_unlock(&lock); - } - - void ReadWriteLock::LockShared() - { - pthread_rwlock_rdlock(&lock); - } - - void ReadWriteLock::ReleaseShared() - { - pthread_rwlock_unlock(&lock); - } - - SingleLatch::SingleLatch() - { - pthread_mutex_init(&mux, NULL); - pthread_cond_init(&cond, NULL); - ready = false; - - Memory::Fence(); - } - - SingleLatch::~SingleLatch() - { - Memory::Fence(); - - pthread_cond_destroy(&cond); - pthread_mutex_destroy(&mux); - } - - void SingleLatch::CountDown() - { - pthread_mutex_lock(&mux); - - if (!ready) { - ready = true; - - pthread_cond_broadcast(&cond); - } - - pthread_mutex_unlock(&mux); - - Memory::Fence(); - } - - void SingleLatch::Await() - { - pthread_mutex_lock(&mux); - - while (!ready) - pthread_cond_wait(&cond, &mux); - - pthread_mutex_unlock(&mux); - - Memory::Fence(); - } - - bool Atomics::CompareAndSet32(int32_t* ptr, int32_t expVal, int32_t newVal) - { - return __sync_bool_compare_and_swap(ptr, expVal, newVal); - } - - int32_t Atomics::CompareAndSet32Val(int32_t* ptr, int32_t expVal, int32_t newVal) - { - return __sync_val_compare_and_swap(ptr, expVal, newVal); - } - - int32_t Atomics::IncrementAndGet32(int32_t* ptr) - { - return __sync_fetch_and_add(ptr, 1) + 1; - } - - int32_t Atomics::DecrementAndGet32(int32_t* ptr) - { - return __sync_fetch_and_sub(ptr, 1) - 1; - } - - bool Atomics::CompareAndSet64(int64_t* ptr, int64_t expVal, int64_t newVal) - { - return __sync_bool_compare_and_swap(ptr, expVal, newVal); - } - - int64_t Atomics::CompareAndSet64Val(int64_t* ptr, int64_t expVal, int64_t newVal) - { - return __sync_val_compare_and_swap(ptr, expVal, newVal); - } - - int64_t Atomics::IncrementAndGet64(int64_t* ptr) - { - return __sync_fetch_and_add(ptr, 1) + 1; - } - - int64_t Atomics::DecrementAndGet64(int64_t* ptr) - { - return __sync_fetch_and_sub(ptr, 1) - 1; - } - - void* ThreadLocal::Get0() - { - pthread_once(&tlsKeyInit, AllocateTlsKey); - - return pthread_getspecific(tlsKey); - } - - void ThreadLocal::Set0(void* ptr) - { - pthread_once(&tlsKeyInit, AllocateTlsKey); - - pthread_setspecific(tlsKey, ptr); - } - } - } - } -} diff --git a/src/odbc/os/linux/src/common/platform_utils.cpp b/src/odbc/os/linux/src/common/platform_utils.cpp deleted file mode 100644 index f0076598f..000000000 --- a/src/odbc/os/linux/src/common/platform_utils.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace ignite -{ - namespace odbc - { - namespace common - { - time_t IgniteTimeGm(const tm& time) - { - tm tmc = time; - - return timegm(&tmc); - } - - time_t IgniteTimeLocal(const tm& time) - { - tm tmc = time; - - return mktime(&tmc); - } - - bool IgniteGmTime(time_t in, tm& out) - { - return gmtime_r(&in, &out) != NULL; - } - - bool IgniteLocalTime(time_t in, tm& out) - { - return localtime_r(&in, &out) == 0; - } - - std::string GetEnv(const std::string& name) - { - static const std::string empty; - - return GetEnv(name, empty); - } - - std::string GetEnv(const std::string& name, const std::string& dflt) - { - char* val0 = std::getenv(name.c_str()); - - if (!val0) - return dflt; - - return std::string(val0); - } - - bool FileExists(const std::string& path) - { - glob_t gs; - - int res = glob(path.c_str(), 0, 0, &gs); - - globfree(&gs); - - return res == 0; - } - - bool IsValidDirectory(const std::string& path) - { - if (path.empty()) - return false; - - struct stat pathStat; - - return stat(path.c_str(), &pathStat) != -1 && S_ISDIR(pathStat.st_mode); - } - - static int rmFiles(const char *pathname, const struct stat*, int, struct FTW*) - { - remove(pathname); - - return 0; - } - - bool DeletePath(const std::string& path) - { - return nftw(path.c_str(), rmFiles, 10, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) == 0; - } - - StdCharOutStream& Fs(StdCharOutStream& ostr) - { - ostr.put('/'); - return ostr; - } - - StdCharOutStream& Dle(StdCharOutStream& ostr) - { - #ifdef __APPLE__ - static const char expansion[] = ".dylib"; - #else - static const char expansion[] = ".so"; - #endif - ostr.write(expansion, sizeof(expansion) - 1); - - return ostr; - } - - IGNITE_IMPORT_EXPORT unsigned GetRandSeed() - { - timespec ts; - - clock_gettime(CLOCK_MONOTONIC, &ts); - - unsigned res = static_cast(ts.tv_sec); - res ^= static_cast(ts.tv_nsec); - res ^= static_cast(getpid()); - - return res; - } - } - } -} diff --git a/src/odbc/os/win/include/ignite/odbc/common/common.h b/src/odbc/os/win/include/ignite/odbc/common/common.h deleted file mode 100644 index e7cda4b52..000000000 --- a/src/odbc/os/win/include/ignite/odbc/common/common.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef _IGNITE_COMMON_COMMON -#define _IGNITE_COMMON_COMMON - -#define IGNITE_EXPORT __declspec(dllexport) -#define IGNITE_IMPORT __declspec(dllimport) -#define IGNITE_CALL __stdcall - -#define IGNITE_IMPORT_EXPORT IGNITE_EXPORT - -#include - -#define IGNITE_TRACE_ALLOC(addr) \ - std::cout << "ALLOC " << __FILE__ << "(" << __LINE__ << "): 0x" << (void*)addr << std::endl; - -/** - * Common construction to disable copy constructor and assignment for class. - */ -#define IGNITE_NO_COPY_ASSIGNMENT(cls) \ - cls(const cls& src); \ - cls& operator= (const cls& other); - -#if (__cplusplus >= 201103L) -# define IGNITE_NO_THROW noexcept -#else -# define IGNITE_NO_THROW throw() -#endif - -#define IGNITE_UNUSED(x) ((void) x) - -#endif //_IGNITE_COMMON_COMMON \ No newline at end of file diff --git a/src/odbc/os/win/include/ignite/odbc/common/concurrent_os.h b/src/odbc/os/win/include/ignite/odbc/common/concurrent_os.h deleted file mode 100644 index 855a995b6..000000000 --- a/src/odbc/os/win/include/ignite/odbc/common/concurrent_os.h +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _IGNITE_ODBC_COMMON_CONCURRENT_OS -#define _IGNITE_ODBC_COMMON_CONCURRENT_OS - -#include - -#include -#include - -#include - -#include "ignite/odbc/common/common.h" -namespace ignite -{ - namespace odbc - { - namespace common - { - namespace concurrent - { - /** - * Static class to manage memory visibility semantics. - */ - class IGNITE_IMPORT_EXPORT Memory - { - public: - /** - * Full fence. - */ - static void Fence(); - }; - - /** - * Critical section. - */ - class IGNITE_IMPORT_EXPORT CriticalSection - { - friend class ConditionVariable; - public: - /** - * Constructor. - */ - CriticalSection(); - - /** - * Destructor. - */ - ~CriticalSection(); - - /** - * Enter critical section. - */ - void Enter(); - - /** - * Leave critical section. - */ - void Leave(); - private: - /** Handle. */ - CRITICAL_SECTION hnd; - - IGNITE_NO_COPY_ASSIGNMENT(CriticalSection) - }; - - class IGNITE_IMPORT_EXPORT ReadWriteLock - { - public: - /** - * Constructor. - */ - ReadWriteLock(); - - /** - * Destructor. - */ - ~ReadWriteLock(); - - /** - * Lock in exclusive mode. - */ - void LockExclusive(); - - /** - * Release in exclusive mode. - */ - void ReleaseExclusive(); - - /** - * Lock in shared mode. - */ - void LockShared(); - - /** - * Release in shared mode. - */ - void ReleaseShared(); - - private: - /** Lock. */ - SRWLOCK lock; - - IGNITE_NO_COPY_ASSIGNMENT(ReadWriteLock) - }; - - /** - * Special latch with count = 1. - */ - class IGNITE_IMPORT_EXPORT SingleLatch - { - public: - /** - * Constructor. - */ - SingleLatch(); - - /** - * Destructor. - */ - ~SingleLatch(); - - /** - * Perform the countdown. - */ - void CountDown(); - - /** - * Await the countdown. - */ - void Await(); - private: - /** Handle. */ - HANDLE hnd = CreateEvent(nullptr, TRUE, FALSE, nullptr); - - IGNITE_NO_COPY_ASSIGNMENT(SingleLatch) - }; - - /** - * Primitives for atomic access. - */ - class IGNITE_IMPORT_EXPORT Atomics - { - public: - /** - * Update the 32-bit integer value if it is equal to expected value. - * - * @param ptr Pointer. - * @param expVal Expected value. - * @param newVal New value. - * @return True if update occurred as a result of this call, false otherwise. - */ - static bool CompareAndSet32(int32_t* ptr, int32_t expVal, int32_t newVal); - - /** - * Update the 32-bit integer value if it is equal to expected value. - * - * @param ptr Pointer. - * @param expVal Expected value. - * @param newVal New value. - * @return Value which were observed during CAS attempt. - */ - static int32_t CompareAndSet32Val(int32_t* ptr, int32_t expVal, int32_t newVal); - - /** - * Increment 32-bit integer and return new value. - * - * @param ptr Pointer. - * @return Value after increment. - */ - static int32_t IncrementAndGet32(int32_t* ptr); - - /** - * Decrement 32-bit integer and return new value. - * - * @param ptr Pointer. - * @return Value after decrement. - */ - static int32_t DecrementAndGet32(int32_t* ptr); - - /** - * Update the 64-bit integer value if it is equal to expected value. - * - * @param ptr Pointer. - * @param expVal Expected value. - * @param newVal New value. - * @return True if update occurred as a result of this call, false otherwise. - */ - static bool CompareAndSet64(int64_t* ptr, int64_t expVal, int64_t newVal); - - /** - * Update the 64-bit integer value if it is equal to expected value. - * - * @param ptr Pointer. - * @param expVal Expected value. - * @param newVal New value. - * @return Value which were observed during CAS attempt. - */ - static int64_t CompareAndSet64Val(int64_t* ptr, int64_t expVal, int64_t newVal); - - /** - * Increment 64-bit integer and return new value. - * - * @param ptr Pointer. - * @return Value after increment. - */ - static int64_t IncrementAndGet64(int64_t* ptr); - - /** - * Decrement 64-bit integer and return new value. - * - * @param ptr Pointer. - * @return Value after decrement. - */ - static int64_t DecrementAndGet64(int64_t* ptr); - }; - - /** - * Thread-local entry. - */ - class IGNITE_IMPORT_EXPORT ThreadLocalEntry - { - public: - /** - * Virtual destructor to allow for correct typed entries cleanup. - */ - virtual ~ThreadLocalEntry() - { - // No-op. - } - }; - - /** - * Typed thread-local entry. - */ - template - class IGNITE_IMPORT_EXPORT ThreadLocalTypedEntry : public ThreadLocalEntry - { - public: - /** - * Constructor. - * - * @param val Value. - */ - ThreadLocalTypedEntry(T val) : val(val) - { - // No-op. - } - - ~ThreadLocalTypedEntry() - { - // No-op. - } - - /** - * Get value. - * - * @return Value. - */ - T Get() - { - return val; - } - private: - /** Value. */ - T val; - }; - - /** - * Thread-local abstraction. - */ - class IGNITE_IMPORT_EXPORT ThreadLocal - { - public: - /** - * Allocate thread-local index. Invoked once on DLL process attach. - * - * @return True if allocation was successful. - */ - static bool OnProcessAttach(); - - /** - * Release thread-local entry. Invoked on DLL thread detach. - */ - static void OnThreadDetach(); - - /** - * Release thread-local index. Invoked once on DLL process detach. - */ - static void OnProcessDetach(); - - /** - * Get next available index to be used in thread-local storage. - * - * @return Index. - */ - static int32_t NextIndex(); - - /** - * Get value by index. - * - * @param idx Index. - * @return Value associated with the index or NULL. - */ - template - static T Get(int32_t idx) - { - void* winVal = Get0(); - - if (winVal) - { - std::map* map = - static_cast*>(winVal); - - ThreadLocalTypedEntry* entry = static_cast*>((*map)[idx]); - - if (entry) - return entry->Get(); - } - - return T(); - } - - /** - * Set value at the given index. - * - * @param idx Index. - * @param val Value to be associated with the index. - */ - template - static void Set(int32_t idx, const T& val) - { - void* winVal = Get0(); - - if (winVal) - { - std::map* map = - static_cast*>(winVal); - - ThreadLocalEntry* appVal = (*map)[idx]; - - if (appVal) - delete appVal; - - (*map)[idx] = new ThreadLocalTypedEntry(val); - } - else - { - std::map* map = new std::map(); - - Set0(map); - - (*map)[idx] = new ThreadLocalTypedEntry(val); - } - } - - /** - * Remove value at the given index. - * - * @param idx Index. - */ - static void Remove(int32_t idx); - - private: - /** - * Internal get routine. - * - * @param Associated value. - */ - static void* Get0(); - - /** - * Internal set routine. - * - * @param ptr Pointer. - */ - static void Set0(void* ptr); - - /** - * Internal thread-local map clear routine. - * - * @param mapPtr Pointer to map. - */ - static void Clear0(void* mapPtr); - }; - - /** - * Thread-local instance. Simplifies API avoiding direct index allocations. - */ - template - class IGNITE_IMPORT_EXPORT ThreadLocalInstance - { - public: - /** - * Constructor. - */ - ThreadLocalInstance() : idx(ThreadLocal::NextIndex()) - { - // No-op. - } - - /** - * Destructor. - */ - ~ThreadLocalInstance() - { - Remove(); - } - - /** - * Get value. - * - * @return Value. - */ - T Get() - { - return ThreadLocal::Get(idx); - } - - /** - * Set instance. - * - * @param val Value. - */ - void Set(const T& val) - { - ThreadLocal::Set(idx, val); - } - - /** - * Remove instance. - */ - void Remove() - { - ThreadLocal::Remove(idx); - } - - private: - /** Index. */ - int32_t idx; - }; - - /** - * Cross-platform wrapper for Condition Variable synchronization - * primitive concept. - */ - class ConditionVariable - { - public: - /** - * Constructor. - */ - ConditionVariable() - { - InitializeConditionVariable(&cond); - } - - /** - * Destructor. - */ - ~ConditionVariable() - { - // No-op. - } - - /** - * Wait for Condition Variable to be notified. - * - * @param cs Critical section in which to wait. - */ - void Wait(CriticalSection& cs) - { - SleepConditionVariableCS(&cond, &cs.hnd, INFINITE); - } - - /** - * Wait for Condition Variable to be notified for specified time. - * - * @param cs Critical section in which to wait. - * @param msTimeout Timeout in milliseconds. - * @return True if the object has been notified and false in case of timeout. - */ - bool WaitFor(CriticalSection& cs, int32_t msTimeout) - { - BOOL notified = SleepConditionVariableCS(&cond, &cs.hnd, msTimeout); - - return notified != FALSE; - } - - /** - * Notify single thread waiting for the condition variable. - */ - void NotifyOne() - { - WakeConditionVariable(&cond); - } - - /** - * Notify all threads that are waiting on the variable. - */ - void NotifyAll() - { - WakeAllConditionVariable(&cond); - } - - private: - IGNITE_NO_COPY_ASSIGNMENT(ConditionVariable); - - /** OS-specific type. */ - CONDITION_VARIABLE cond; - }; - - /** - * Manually triggered event. - * Once triggered it stays in passing state until manually reset. - */ - class ManualEvent - { - public: - /** - * Constructs manual event. - * Initial state is untriggered. - */ - ManualEvent() - { - handle = CreateEvent(NULL, TRUE, FALSE, NULL); - - assert(handle != NULL); - } - - /** - * Destructor. - */ - ~ManualEvent() - { - CloseHandle(handle); - } - - /** - * Sets event into triggered state. - */ - void Set() - { - BOOL success = SetEvent(handle); - - assert(success); - } - - /** - * Resets event into non-triggered state. - */ - void Reset() - { - BOOL success = ResetEvent(handle); - - assert(success); - } - - /** - * Wait for event to be triggered. - */ - void Wait() - { - DWORD res = WaitForSingleObject(handle, INFINITE); - - assert(res == WAIT_OBJECT_0); - } - - /** - * Wait for event to be triggered for specified time. - * - * @param msTimeout Timeout in milliseconds. - * @return True if the object has been triggered and false in case of timeout. - */ - bool WaitFor(int32_t msTimeout) - { - DWORD res = WaitForSingleObject(handle, static_cast(msTimeout)); - - assert(res == WAIT_OBJECT_0 || res == WAIT_TIMEOUT); - - return res == WAIT_OBJECT_0; - } - - private: - IGNITE_NO_COPY_ASSIGNMENT(ManualEvent); - - /** Event handle. */ - HANDLE handle; - }; - } - } - } -} - -#endif //_IGNITE_ODBC_COMMON_CONCURRENT_OS diff --git a/src/odbc/os/win/src/common/concurrent_os.cpp b/src/odbc/os/win/src/common/concurrent_os.cpp deleted file mode 100644 index 71f5587db..000000000 --- a/src/odbc/os/win/src/common/concurrent_os.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ignite/odbc/common/concurrent_os.h" - -#pragma intrinsic(_InterlockedCompareExchange64) - -namespace ignite -{ - namespace odbc - { - namespace common - { - namespace concurrent - { - /** Thread-local index for Windows. */ - DWORD winTlsIdx; - - void Memory::Fence() { - MemoryBarrier(); - } - - CriticalSection::CriticalSection() : - hnd() - { - InitializeCriticalSection(&hnd); - - Memory::Fence(); - } - - CriticalSection::~CriticalSection() = default; - - void CriticalSection::Enter() - { - Memory::Fence(); - - EnterCriticalSection(&hnd); - } - - void CriticalSection::Leave() - { - Memory::Fence(); - - LeaveCriticalSection(&hnd); - } - - ReadWriteLock::ReadWriteLock() : - lock() - { - InitializeSRWLock(&lock); - - Memory::Fence(); - } - - ReadWriteLock::~ReadWriteLock() = default; - - void ReadWriteLock::LockExclusive() - { - AcquireSRWLockExclusive(&lock); - } - - void ReadWriteLock::ReleaseExclusive() - { - ReleaseSRWLockExclusive(&lock); - } - - void ReadWriteLock::LockShared() - { - AcquireSRWLockShared(&lock); - } - - void ReadWriteLock::ReleaseShared() - { - ReleaseSRWLockShared(&lock); - } - - SingleLatch::SingleLatch() - { - Memory::Fence(); - } - - SingleLatch::~SingleLatch() - { - Memory::Fence(); - - CloseHandle(hnd); - } - - void SingleLatch::CountDown() - { - SetEvent(hnd); - } - - void SingleLatch::Await() - { - WaitForSingleObject(hnd, INFINITE); - } - - bool Atomics::CompareAndSet32(int32_t* ptr, int32_t expVal, int32_t newVal) - { - return CompareAndSet32Val(ptr, expVal, newVal) == expVal; - } - - int32_t Atomics::CompareAndSet32Val(int32_t* ptr, int32_t expVal, int32_t newVal) - { - return InterlockedCompareExchange(reinterpret_cast(ptr), newVal, expVal); - } - - int32_t Atomics::IncrementAndGet32(int32_t* ptr) - { - return InterlockedIncrement(reinterpret_cast(ptr)); - } - - int32_t Atomics::DecrementAndGet32(int32_t* ptr) - { - return InterlockedDecrement(reinterpret_cast(ptr)); - } - - bool Atomics::CompareAndSet64(int64_t* ptr, int64_t expVal, int64_t newVal) - { - return CompareAndSet64Val(ptr, expVal, newVal) == expVal; - } - - int64_t Atomics::CompareAndSet64Val(int64_t* ptr, int64_t expVal, int64_t newVal) - { - return _InterlockedCompareExchange64(ptr, newVal, expVal); - } - - int64_t Atomics::IncrementAndGet64(int64_t* ptr) - { - #ifdef _WIN64 - return InterlockedIncrement64(ptr); - #else - while (true) - { - int64_t expVal = *ptr; - int64_t newVal = expVal + 1; - - if (CompareAndSet64(ptr, expVal, newVal)) - return newVal; - } - #endif - } - - int64_t Atomics::DecrementAndGet64(int64_t* ptr) - { - #ifdef _WIN64 - return InterlockedDecrement64(ptr); - #else - while (true) - { - int64_t expVal = *ptr; - int64_t newVal = expVal - 1; - - if (CompareAndSet64(ptr, expVal, newVal)) - return newVal; - } - #endif - } - - bool ThreadLocal::OnProcessAttach() - { - return (winTlsIdx = TlsAlloc()) != TLS_OUT_OF_INDEXES; - } - - void ThreadLocal::OnThreadDetach() - { - if (winTlsIdx != TLS_OUT_OF_INDEXES) - { - void* mapPtr = Get0(); - - Clear0(mapPtr); - } - } - - void ThreadLocal::OnProcessDetach() - { - if (winTlsIdx != TLS_OUT_OF_INDEXES) - TlsFree(winTlsIdx); - } - - void* ThreadLocal::Get0() - { - return TlsGetValue(winTlsIdx); - } - - void ThreadLocal::Set0(void* ptr) - { - TlsSetValue(winTlsIdx, ptr); - } - } - } - } -} diff --git a/src/odbc/os/win/src/common/platform_utils.cpp b/src/odbc/os/win/src/common/platform_utils.cpp deleted file mode 100644 index 35261fa0d..000000000 --- a/src/odbc/os/win/src/common/platform_utils.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include - -#include - -namespace ignite { - namespace odbc - { - namespace common - { - time_t IgniteTimeGm(const tm& time) - { - tm tmc = time; - - return _mkgmtime(&tmc); - } - - time_t IgniteTimeLocal(const tm& time) - { - tm tmc = time; - - return mktime(&tmc); - } - - bool IgniteGmTime(time_t in, tm& out) - { - return gmtime_s(&out, &in) == 0; - } - - bool IgniteLocalTime(time_t in, tm& out) - { - return localtime_s(&out, &in) == 0; - } - - std::string GetEnv(const std::string& name) - { - static const std::string empty; - - return GetEnv(name, empty); - } - - std::string GetEnv(const std::string& name, const std::string& dflt) - { - char res[32767]; - - DWORD envRes = GetEnvironmentVariableA(name.c_str(), res, sizeof(res) / sizeof(res[0])); - - if (envRes == 0 || envRes > sizeof(res)) - return dflt; - - return std::string(res, static_cast(envRes)); - } - - bool FileExists(const std::string& path) - { - WIN32_FIND_DATAA findres; - - HANDLE hnd = FindFirstFileA(path.c_str(), &findres); - - if (hnd == INVALID_HANDLE_VALUE) - return false; - - FindClose(hnd); - - return true; - } - - bool IsValidDirectory(const std::string& path) - { - if (path.empty()) - return false; - - DWORD attrs = GetFileAttributesA(path.c_str()); - - return attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0; - } - - bool DeletePath(const std::string& path) - { - std::vector path0(path.begin(), path.end()); - path0.push_back('\0'); - path0.push_back('\0'); - - SHFILEOPSTRUCT fileop; - fileop.hwnd = nullptr; - fileop.wFunc = FO_DELETE; - fileop.pFrom = &path0[0]; - fileop.pTo = nullptr; - fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; - - fileop.fAnyOperationsAborted = FALSE; - fileop.lpszProgressTitle = nullptr; - fileop.hNameMappings = nullptr; - - int ret = SHFileOperation(&fileop); - - return ret == 0; - } - - StdCharOutStream& Fs(StdCharOutStream& ostr) - { - ostr.put('\\'); - return ostr; - } - - StdCharOutStream& Dle(StdCharOutStream& ostr) - { - static const char expansion[] = ".dll"; - - ostr.write(expansion, sizeof(expansion) - 1); - - return ostr; - } - - IGNITE_IMPORT_EXPORT unsigned GetRandSeed() - { - return static_cast(GetTickCount64() ^ GetCurrentProcessId()); - } - } - } -} diff --git a/src/odbc/os/win/src/system/ui/window.cpp b/src/odbc/os/win/src/system/ui/window.cpp index 8512bda8a..02d62e2d8 100644 --- a/src/odbc/os/win/src/system/ui/window.cpp +++ b/src/odbc/os/win/src/system/ui/window.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include "ignite/odbc/system/ui/window.h" @@ -58,7 +58,7 @@ namespace ignite title(), handle(handle), created(false), - parent(nullptr) + parent(0) { // No-op. } @@ -88,7 +88,7 @@ namespace ignite posY, width, height, - parent ? parent->GetHandle() : nullptr, + parent ? parent->GetHandle() : NULL, reinterpret_cast(static_cast(id)), GetHInstance(), this @@ -125,7 +125,7 @@ namespace ignite if (handle) DestroyWindow(handle); - handle = nullptr; + handle = NULL; } void Window::GetText(std::string& text) const diff --git a/src/odbc/src/app/application_data_buffer.cpp b/src/odbc/src/app/application_data_buffer.cpp index f4977bb09..2942defc8 100644 --- a/src/odbc/src/app/application_data_buffer.cpp +++ b/src/odbc/src/app/application_data_buffer.cpp @@ -19,7 +19,7 @@ #include #include -#include "ignite/odbc/common/bits.h" +#include "ignite/common/bits.h" #include "ignite/impl/binary/binary_utils.h" diff --git a/src/odbc/src/common/big_integer.cpp b/src/odbc/src/common/big_integer.cpp deleted file mode 100644 index 3114a452f..000000000 --- a/src/odbc/src/common/big_integer.cpp +++ /dev/null @@ -1,866 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ignite/odbc/ignite_error.h" -#include "ignite/odbc/common/bits.h" -#include "ignite/odbc/common/big_integer.h" - -namespace ignite -{ - namespace odbc - { - namespace common - { - BigInteger::BigInteger() : - sign(1), - mag() - { - // No-op. - } - - BigInteger::BigInteger(int64_t val) : - sign(1), - mag() - { - AssignInt64(val); - } - - BigInteger::BigInteger(const char* val, int32_t len) : - sign(1), - mag() - { - AssignString(val, len); - } - - BigInteger::BigInteger(const BigInteger& other) : - sign(other.sign), - mag(other.mag) - { - // No-op. - } - - BigInteger::BigInteger(const int8_t* val, int32_t len, int32_t sign, bool bigEndian) : - sign(sign), - mag() - { - assert(val != 0); - assert(len >= 0); - assert(sign == 1 || sign == 0 || sign == -1); - - if (bigEndian) - { - int32_t firstNonZero = 0; - while (firstNonZero < len && val[firstNonZero] == 0) - ++firstNonZero; - - if (firstNonZero == len) - { - AssignInt64(0); - - return; - } - - int32_t intLength = (len - firstNonZero + 3) / 4; - - mag.Resize(intLength); - - int32_t b = len - 1; - - for (int32_t i = 0; i < intLength - 1; ++i) - { - mag[i] = (val[b] & 0xFFUL) - | ((val[b - 1] & 0xFFUL) << 8) - | ((val[b - 2] & 0xFFUL) << 16) - | ((val[b - 3] & 0xFFUL) << 24); - - b -= 4; - } - - int32_t bytesRemaining = b - firstNonZero + 1; - - assert(bytesRemaining > 0 && bytesRemaining <= 4); - - switch (bytesRemaining) - { - case 4: - mag[intLength - 1] |= (val[b - 3] & 0xFF) << 24; - // Fall-through. - - case 3: - mag[intLength - 1] |= (val[b - 2] & 0xFF) << 16; - // Fall-through. - - case 2: - mag[intLength - 1] |= (val[b - 1] & 0xFF) << 8; - // Fall-through. - - case 1: - mag[intLength - 1] |= val[b] & 0xFF; - // Fall-through. - - default: - break; - } - } - else - { - int32_t firstNonZero = len - 1; - - while (firstNonZero >= 0 && val[firstNonZero] == 0) - --firstNonZero; - - if (firstNonZero == -1) - { - AssignInt64(0); - - return; - } - - int32_t intLength = (firstNonZero + 4) / 4; - - mag.Resize(intLength); - - int32_t b = 0; - - for (int32_t i = 0; i < intLength - 1; ++i) - { - mag[i] = (val[b] & 0xFFUL) - | ((val[b + 1] & 0xFFUL) << 8) - | ((val[b + 2] & 0xFFUL) << 16) - | ((val[b + 3] & 0xFFUL) << 24); - - b += 4; - } - - int32_t bytesRemaining = firstNonZero - b + 1; - - assert(bytesRemaining > 0 && bytesRemaining <= 4); - - switch (bytesRemaining) - { - case 4: - mag[intLength - 1] |= (val[b + 3] & 0xFF) << 24; - // Fall-through. - - case 3: - mag[intLength - 1] |= (val[b + 2] & 0xFF) << 16; - // Fall-through. - - case 2: - mag[intLength - 1] |= (val[b + 1] & 0xFF) << 8; - // Fall-through. - - case 1: - mag[intLength - 1] |= val[b] & 0xFF; - // Fall-through. - - default: - break; - } - } - } - - BigInteger::BigInteger(MagArray &mag, int8_t sign) : - sign(sign), - mag() - { - this->mag.Swap(mag); - } - - BigInteger& BigInteger::operator=(const BigInteger& other) - { - Assign(other); - - return *this; - } - - void BigInteger::Assign(const BigInteger& val) - { - if (this != &val) - { - sign = val.sign; - mag = val.mag; - } - } - - void BigInteger::AssignInt64(int64_t val) - { - if (val < 0) - { - AssignUint64(static_cast(-val)); - - sign = -1; - } - else - AssignUint64(static_cast(val)); - } - - void BigInteger::AssignString(const char* val, int32_t len) - { - std::stringstream converter; - - converter.write(val, len); - - converter >> *this; - } - - void BigInteger::AssignUint64(uint64_t val) - { - sign = 1; - - if (val == 0) - { - mag.Clear(); - - return; - } - - uint32_t highWord = static_cast(val >> 32); - - if (highWord == 0) - mag.Resize(1); - else - { - mag.Resize(2); - mag[1] = highWord; - } - - mag[0] = static_cast(val); - } - - int8_t BigInteger::GetSign() const - { - return sign; - } - - void BigInteger::Swap(BigInteger& other) - { - using std::swap; - - swap(sign, other.sign); - mag.Swap(other.mag); - } - - const BigInteger::MagArray& BigInteger::GetMagnitude() const - { - return mag; - } - - uint32_t BigInteger::GetBitLength() const - { - if (mag.IsEmpty()) - return 0; - - int32_t res = bits::BitLengthU32(mag[mag.GetSize() - 1]); - - if (mag.GetSize() > 1) - res += (mag.GetSize() - 1) * 32; - - return res; - } - - int32_t BigInteger::GetPrecision() const - { - // See http://graphics.stanford.edu/~seander/bithacks.html - // for the details on the algorithm. - - if (mag.GetSize() == 0) - return 1; - - int32_t r = static_cast((( - static_cast(GetBitLength()) + 1) * 646456993) >> 31); - - BigInteger prec; - BigInteger::GetPowerOfTen(r, prec); - - return Compare(prec, true) < 0 ? r : r + 1; - } - - void BigInteger::MagnitudeToBytes(common::FixedSizeArray& buffer) const - { - int32_t bytesNum = static_cast((GetBitLength() + 7) / 8); - - if (bytesNum == 0) - { - buffer.Reset(1); - - return; - } - - buffer.Reset(bytesNum); - - int32_t i; - for (i = 0; i < mag.GetSize() - 1; ++i) - { - int32_t j = bytesNum - 1 - 4 * i; - - buffer[j] = static_cast(mag[i]); - buffer[j - 1] = static_cast(mag[i] >> 8); - buffer[j - 2] = static_cast(mag[i] >> 16); - buffer[j - 3] = static_cast(mag[i] >> 24); - } - - int32_t bytesRemaining = bytesNum - 4 * i; - - assert(bytesRemaining >= 0 && bytesRemaining <= 4); - - i = 0; - switch (bytesRemaining) - { - case 4: - buffer[i++] |= static_cast(mag[mag.GetSize() - 1] >> 24); - // Fall-through. - - case 3: - buffer[i++] |= static_cast(mag[mag.GetSize() - 1] >> 16); - // Fall-through. - - case 2: - buffer[i++] |= static_cast(mag[mag.GetSize() - 1] >> 8); - // Fall-through. - - case 1: - buffer[i++] |= static_cast(mag[mag.GetSize() - 1]); - // Fall-through. - - default: - break; - } - } - - void BigInteger::Pow(int32_t exp) - { - if (exp < 0) - { - AssignInt64(0); - - return; - } - - uint32_t bitsLen = GetBitLength(); - - if (!bitsLen) - return; - - if (bitsLen == 1) - { - if ((exp % 2 == 0) && sign < 0) - sign = -sign; - - return; - } - - BigInteger multiplicant(*this); - AssignInt64(1); - - int32_t mutExp = exp; - while (mutExp) - { - if (mutExp & 1) - Multiply(multiplicant, *this); - - mutExp >>= 1; - - if (mutExp) - multiplicant.Multiply(multiplicant, multiplicant); - } - } - - void BigInteger::Multiply(const BigInteger& other, BigInteger& res) const - { - MagArray resMag(mag.GetSize() + other.mag.GetSize()); - - resMag.Resize(mag.GetSize() + other.mag.GetSize()); - - for (int32_t i = 0; i < other.mag.GetSize(); ++i) - { - uint32_t carry = 0; - - for (int32_t j = 0; j < mag.GetSize(); ++j) - { - uint64_t product = static_cast(mag[j]) * other.mag[i] + - + resMag[i + j] + carry; - - resMag[i + j] = static_cast(product); - carry = static_cast(product >> 32); - } - - resMag[i + mag.GetSize()] = carry; - } - - res.mag.Swap(resMag); - res.sign = sign * other.sign; - - res.Normalize(); - } - - /** - * Shift magnitude left by the specified number of bits. - * - * @param in Input magnitude. - * @param len Magnitude length. - * @param out Output magnitude. Should be not shorter than the input - * magnitude. - * @param n Number of bits to shift to. - */ - void ShiftLeft(const uint32_t* in, int32_t len, uint32_t* out, unsigned n) - { - assert(n < 32); - - if (n == 0) - { - std::copy(in, in + len, out); - - return; - } - - for (int32_t i = len - 1; i > 0; --i) - out[i] = (in[i] << n) | (in[i - 1] >> (32 - n)); - - out[0] = in[0] << n; - } - - /** - * Shift magnitude right by the specified number of bits. - * - * @param in Input magnitude. - * @param len Magnitude length. - * @param out Output magnitude. Should be not shorter than the input - * magnitude. - * @param n Number of bits to shift to. - */ - void ShiftRight(const uint32_t* in, int32_t len, uint32_t* out, unsigned n) - { - assert(n < 32); - - if (n == 0) - { - std::copy(in, in + len, out); - - return; - } - - for (int32_t i = 0; i < len - 1; ++i) - out[i] = (in[i] >> n) | (in[i + 1] << (32 - n)); - - out[len - 1] = in[len - 1] >> n; - } - - /** - * Part of the division algorithm. Computes q - (a * x). - * - * @param q Minuend. - * @param a Multipliplier of the subtrahend. - * @param alen Length of the a. - * @param x Multipliplicand of the subtrahend. - * @return Carry. - */ - uint32_t MultiplyAndSubstruct(uint32_t* q, const uint32_t* a, int32_t alen, uint32_t x) - { - uint64_t carry = 0; - - for (int32_t i = 0; i < alen; ++i) - { - uint64_t product = a[i] * static_cast(x); - int64_t difference = q[i] - carry - (product & 0xFFFFFFFF); - - q[i] = static_cast(difference); - - // This will add one if difference is negative. - carry = (product >> 32) - (difference >> 32); - } - - return static_cast(carry); - } - - /** - * Add two magnitude arrays and return carry. - * - * @param res First addend. Result is placed here. Length of this addend - * should be equal or greater than len. - * @param addend Second addend. - * @param len Length of the second addend. - * @return Carry. - */ - uint32_t Add(uint32_t* res, const uint32_t* addend, int32_t len) - { - uint64_t carry = 0; - - for (int32_t i = 0; i < len; ++i) - { - uint64_t sum = static_cast(res[i]) + addend[i] + carry; - res[i] = static_cast(sum); - carry = sum >> 32; - } - - return static_cast(carry); - } - - /** - * Add single number to a magnitude array and return carry. - * - * @param res First addend. Result is placed here. Length of this addend - * should be equal or greater than len. - * @param len Length of the First addend. - * @param addend Second addend. - * @return Carry. - */ - uint32_t Add(uint32_t* res, int32_t len, uint32_t addend) - { - uint64_t carry = addend; - - for (int32_t i = 0; (i < len) && carry; ++i) - { - uint64_t sum = static_cast(res[i]) + carry; - res[i] = static_cast(sum); - carry = sum >> 32; - } - - return static_cast(carry); - } - - void BigInteger::Divide(const BigInteger& divisor, BigInteger& res) const - { - Divide(divisor, res, 0); - } - - void BigInteger::Divide(const BigInteger& divisor, BigInteger& res, BigInteger& rem) const - { - Divide(divisor, res, &rem); - } - - void BigInteger::Add(const uint32_t* addend, int32_t len) - { - if (mag.GetSize() < len) - { - mag.Reserve(len + 1); - - mag.Resize(len); - } - else - mag.Reserve(mag.GetSize() + 1); - - uint32_t carry = common::Add(mag.GetData(), addend, len); - - if (carry) - { - carry = common::Add(mag.GetData() + len, mag.GetSize() - len, carry); - - if (carry) - mag.PushBack(carry); - } - } - - void BigInteger::Add(uint64_t x) - { - if (x == 0) - return; - - if (IsZero()) - { - AssignUint64(x); - - return; - } - - uint32_t val[2]; - - val[0] = static_cast(x); - val[1] = static_cast(x >> 32); - - Add(val, val[1] ? 2 : 1); - } - - int32_t BigInteger::Compare(const BigInteger& other, bool ignoreSign) const - { - // What we should return if magnitude is greater. - int32_t mgt = 1; - - if (!ignoreSign) - { - if (sign != other.sign) - return sign > other.sign ? 1 : -1; - else - mgt = sign; - } - - if (mag.GetSize() != other.mag.GetSize()) - return mag.GetSize() > other.mag.GetSize() ? mgt : -mgt; - - for (int32_t i = mag.GetSize() - 1; i >= 0; --i) - { - if (mag[i] == other.mag[i]) - continue; - else if (mag[i] > other.mag[i]) - return mgt; - else - return -mgt; - } - - return 0; - } - - int64_t BigInteger::ToInt64() const - { - return (static_cast(GetMagInt(1)) << 32) | GetMagInt(0); - } - - void BigInteger::GetPowerOfTen(int32_t pow, BigInteger& res) - { - using namespace common; - - assert(pow >= 0); - - if (pow < bits::UINT64_MAX_PRECISION) - { - res.AssignUint64(bits::TenPowerU64(pow)); - - return; - } - - res.AssignInt64(10); - res.Pow(pow); - } - - uint32_t BigInteger::GetMagInt(int32_t n) const - { - assert(n >= 0); - - if (n >= mag.GetSize()) - return sign > 0 ? 0 : -1; - - return sign * mag[n]; - } - - void BigInteger::Divide(const BigInteger& divisor, BigInteger& res, BigInteger* rem) const - { - // Can't divide by zero. - if (divisor.mag.IsEmpty()) - throw IgniteError(IgniteError::IGNITE_ERR_ILLEGAL_ARGUMENT, "Division by zero."); - - int32_t compRes = Compare(divisor, true); - - int8_t resSign = sign * divisor.sign; - - // The same magnitude. Result is [-]1 and remainder is zero. - if (compRes == 0) - { - res.AssignInt64(resSign); - - if (rem) - rem->AssignInt64(0); - - return; - } - - // Divisor is greater than this. Result is 0 and remainder is this. - if (compRes == -1) - { - // Order is important here! Copy to rem first to handle the case - // when &res == this. - if (rem) - rem->Assign(*this); - - res.AssignInt64(0); - - return; - } - - // If divisor is [-]1 result is [-]this and remainder is zero. - if (divisor.GetBitLength() == 1) - { - // Once again: order is important. - res.Assign(*this); - res.sign = sign * divisor.sign; - - if (rem) - rem->AssignInt64(0); - - return; - } - - // Trivial case. - if (mag.GetSize() <= 2) - { - uint64_t u = mag[0]; - uint64_t v = divisor.mag[0]; - - if (mag.GetSize() == 2) - u |= static_cast(mag[1]) << 32; - - if (divisor.mag.GetSize() == 2) - v |= static_cast(divisor.mag[1]) << 32; - - // Divisor can not be 1, or 0. - assert(v > 1); - - // It should also be less than dividend. - assert(v < u); - - // (u / v) is always fits into int64_t because abs(v) >= 2. - res.AssignInt64(resSign * static_cast(u / v)); - - // (u % v) is always fits into int64_t because (u > v) -> - // (u % v) < (u / 2). - if (rem) - rem->AssignInt64(resSign * static_cast(u % v)); - - return; - } - - // Using Knuth division algorithm D for common case. - - // Short aliases. - const MagArray& u = mag; - const MagArray& v = divisor.mag; - MagArray& q = res.mag; - int32_t ulen = u.GetSize(); - int32_t vlen = v.GetSize(); - - // First we need to normilize divisor. - MagArray nv; - nv.Resize(v.GetSize()); - - int32_t shift = bits::NumberOfLeadingZerosU32(v.Back()); - ShiftLeft(v.GetData(), vlen, nv.GetData(), shift); - - // Divisor is normilized. Now we need to normilize divident. - MagArray nu; - - // First find out what is the size of it. - if (bits::NumberOfLeadingZerosU32(u.Back()) >= shift) - { - // Everything is the same as with divisor. Just add leading zero. - nu.Resize(ulen + 1); - - ShiftLeft(u.GetData(), ulen, nu.GetData(), shift); - - assert((static_cast(u.Back()) >> (32 - shift)) == 0); - } - else - { - // We need one more byte here. Also adding leading zero. - nu.Resize(ulen + 2); - - ShiftLeft(u.GetData(), ulen, nu.GetData(), shift); - - nu[ulen] = u[ulen - 1] >> (32 - shift); - - assert(nu[ulen] != 0); - } - - assert(nu.Back() == 0); - - // Resizing resulting array. - q.Resize(ulen - vlen + 1); - - // Main loop - for (int32_t i = ulen - vlen; i >= 0; --i) - { - uint64_t base = bits::MakeU64(nu[i + vlen], nu[i + vlen - 1]); - - uint64_t qhat = base / nv[vlen - 1]; // Estimated quotient. - uint64_t rhat = base % nv[vlen - 1]; // A remainder. - - // Adjusting result if needed. - while (qhat > UINT32_MAX || - ((qhat * nv[vlen - 2]) > ((UINT32_MAX + static_cast(1)) * rhat + nu[i + vlen - 2]))) - { - --qhat; - rhat += nv[vlen - 1]; - - if (rhat > UINT32_MAX) - break; - } - - uint32_t qhat32 = static_cast(qhat); - - // Multiply and subtract. - uint32_t carry = MultiplyAndSubstruct(nu.GetData() + i, nv.GetData(), vlen, qhat32); - - int64_t difference = nu[i + vlen] - carry; - - nu[i + vlen] = static_cast(difference); - - if (difference < 0) - { - --qhat32; - carry = common::Add(nu.GetData() + i, nv.GetData(), vlen); - - assert(carry == 0); - } - - q[i] = qhat32; - } - - res.sign = resSign; - res.Normalize(); - - // If remainder is needed unnormolize it. - if (rem) - { - rem->sign = resSign; - rem->mag.Resize(vlen); - - ShiftRight(nu.GetData(), rem->mag.GetSize(), rem->mag.GetData(), shift); - - rem->Normalize(); - } - } - - void BigInteger::Normalize() - { - int32_t lastNonZero = mag.GetSize() - 1; - while (lastNonZero >= 0 && mag[lastNonZero] == 0) - --lastNonZero; - - mag.Resize(lastNonZero + 1); - } - - bool operator==(const BigInteger& val1, const BigInteger& val2) - { - return val1.Compare(val2) == 0; - } - - bool operator!=(const BigInteger& val1, const BigInteger& val2) - { - return val1.Compare(val2) != 0; - } - - bool operator<(const BigInteger& val1, const BigInteger& val2) - { - return val1.Compare(val2) < 0; - } - - bool operator<=(const BigInteger& val1, const BigInteger& val2) - { - return val1.Compare(val2) <= 0; - } - - bool operator>(const BigInteger& val1, const BigInteger& val2) - { - return val1.Compare(val2) > 0; - } - - bool operator>=(const BigInteger& val1, const BigInteger& val2) - { - return val1.Compare(val2) >= 0; - } - } - } -} - diff --git a/src/odbc/src/common/bits.cpp b/src/odbc/src/common/bits.cpp deleted file mode 100644 index a5c922a8b..000000000 --- a/src/odbc/src/common/bits.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "ignite/odbc/common/bits.h" - -namespace ignite -{ - namespace odbc - { - namespace common - { - namespace bits - { - int32_t NumberOfTrailingZerosI32(int32_t i) - { - int32_t y; - - if (i == 0) return 32; - - int32_t n = 31; - - y = i << 16; - - if (y != 0) { - n = n - 16; - i = y; - } - - y = i << 8; - - if (y != 0) { - n = n - 8; - i = y; - } - - y = i << 4; - - if (y != 0) { - n = n - 4; - i = y; - } - - y = i << 2; - - if (y != 0) { - n = n - 2; - i = y; - } - - return n - static_cast(static_cast(i << 1) >> 31); - } - - int32_t NumberOfLeadingZerosI32(int32_t i) - { - return NumberOfLeadingZerosU32(static_cast(i)); - } - - int32_t NumberOfLeadingZerosU32(uint32_t i) - { - if (i == 0) - return 32; - - int32_t n = 1; - - if (i >> 16 == 0) { - n += 16; - i <<= 16; - } - - if (i >> 24 == 0) { - n += 8; - i <<= 8; - } - - if (i >> 28 == 0) { - n += 4; - i <<= 4; - } - - if (i >> 30 == 0) { - n += 2; - i <<= 2; - } - - return n - static_cast(i >> 31); - } - - int32_t NumberOfLeadingZerosI64(int64_t i) - { - return NumberOfLeadingZerosU64(static_cast(i)); - } - - int32_t NumberOfLeadingZerosU64(uint64_t i) - { - if (i == 0) - return 64; - - int32_t n = 1; - - uint32_t x = static_cast(i >> 32); - - if (x == 0) { - n += 32; - x = static_cast(i); - } - - if (x >> 16 == 0) { - n += 16; - x <<= 16; - } - - if (x >> 24 == 0) { - n += 8; - x <<= 8; - } - - if (x >> 28 == 0) { - n += 4; - x <<= 4; - } - - if (x >> 30 == 0) { - n += 2; - x <<= 2; - } - - n -= x >> 31; - - return n; - } - - int32_t BitCountI32(int32_t i) - { - uint32_t ui = static_cast(i); - - ui -= (ui >> 1) & 0x55555555; - ui = (ui & 0x33333333) + ((ui >> 2) & 0x33333333); - ui = (ui + (ui >> 4)) & 0x0f0f0f0f; - ui += ui >> 8; - ui += ui >> 16; - - return static_cast(ui & 0x3f); - } - - int32_t BitLengthI32(int32_t i) - { - return 32 - NumberOfLeadingZerosI32(i); - } - - int32_t BitLengthU32(uint32_t i) - { - return 32 - NumberOfLeadingZerosU32(i); - } - - int32_t GetCapasityForSize(int32_t size) - { - assert(size > 0); - - if (size <= 8) - return 8; - - int32_t bl = BitLengthI32(size); - - if (bl > 30) - return INT32_MAX; - - int32_t res = 1 << bl; - - return size > res ? res << 1 : res; - } - - int32_t DigitLength(uint64_t x) - { - // See http://graphics.stanford.edu/~seander/bithacks.html - // for the details on the algorithm. - - if (x < 10) - return 1; - - int32_t r = ((64 - NumberOfLeadingZerosU64(x) + 1) * 1233) >> 12; - - assert(r <= UINT64_MAX_PRECISION); - - return (r == UINT64_MAX_PRECISION || x < TenPowerU64(r)) ? r : r + 1; - } - - uint64_t TenPowerU64(int32_t n) - { - static const uint64_t TEN_POWERS_TABLE[UINT64_MAX_PRECISION] = { - 1U, // 0 / 10^0 - 10U, // 1 / 10^1 - 100U, // 2 / 10^2 - 1000U, // 3 / 10^3 - 10000U, // 4 / 10^4 - 100000U, // 5 / 10^5 - 1000000U, // 6 / 10^6 - 10000000U, // 7 / 10^7 - 100000000U, // 8 / 10^8 - 1000000000U, // 9 / 10^9 - 10000000000U, // 10 / 10^10 - 100000000000U, // 11 / 10^11 - 1000000000000U, // 12 / 10^12 - 10000000000000U, // 13 / 10^13 - 100000000000000U, // 14 / 10^14 - 1000000000000000U, // 15 / 10^15 - 10000000000000000U, // 16 / 10^16 - 100000000000000000U, // 17 / 10^17 - 1000000000000000000U, // 18 / 10^18 - 10000000000000000000U // 19 / 10^19 - }; - - assert(n >= 0 && n < UINT64_MAX_PRECISION); - - return TEN_POWERS_TABLE[n]; - } - } - } - } -} diff --git a/src/odbc/src/common/concurrent.cpp b/src/odbc/src/common/concurrent.cpp deleted file mode 100644 index 1d041644c..000000000 --- a/src/odbc/src/common/concurrent.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ignite/odbc/common/concurrent.h" - -namespace ignite -{ - namespace odbc - { - namespace common - { - namespace concurrent - { - /** Thread-local index generator for application. */ - int32_t appTlsIdxGen = 0; - - int32_t ThreadLocal::NextIndex() - { - return Atomics::IncrementAndGet32(&appTlsIdxGen); - } - - void ThreadLocal::Remove(int32_t idx) - { - void* val = Get0(); - - if (val) - { - std::map* map = - static_cast*>(val); - - ThreadLocalEntry* appVal = (*map)[idx]; - - if (appVal) - delete appVal; - - map->erase(idx); - - if (map->size() == 0) - { - delete map; - - Set0(NULL); - } - } - } - - void ThreadLocal::Clear0(void* mapPtr) - { - if (mapPtr) - { - std::map* map = - static_cast*>(mapPtr); - - for (std::map::iterator it = map->begin(); it != map->end(); ++it) - delete it->second; - - delete map; - } - } - - SharedPointerImpl::SharedPointerImpl(void* ptr, DeleterType deleter) : - ptr(ptr), deleter(deleter), refCnt(1) - { - Memory::Fence(); - } - - void* SharedPointerImpl::Pointer() - { - return ptr; - } - - const void* SharedPointerImpl::Pointer() const - { - return ptr; - } - - SharedPointerImpl::DeleterType SharedPointerImpl::Deleter() - { - return deleter; - } - - void SharedPointerImpl::Increment() - { - Atomics::IncrementAndGet32(&refCnt); - } - - bool SharedPointerImpl::Decrement() - { - return Atomics::DecrementAndGet32(&refCnt) == 0; - } - } - } - } -} diff --git a/src/odbc/src/common/decimal.cpp b/src/odbc/src/common/decimal.cpp deleted file mode 100644 index 40d597547..000000000 --- a/src/odbc/src/common/decimal.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "ignite/odbc/common/utils.h" -#include "ignite/odbc/common/decimal.h" - -using ignite::odbc::common::BigInteger; - -namespace ignite -{ - namespace odbc - { - namespace common - { - Decimal::Decimal() : - scale(0), - magnitude(0) - { - // No-op. - } - - Decimal::Decimal(const int8_t* mag, int32_t len, int32_t scale, int32_t sign, bool bigEndian) : - scale(scale & 0x7FFFFFFF), - magnitude(mag, len, sign, bigEndian) - { - // No-op. - } - - Decimal::Decimal(const Decimal& other) : - scale(other.scale), - magnitude(other.magnitude) - { - // No-op. - } - - Decimal::Decimal(int64_t val) : - scale(0), - magnitude(val) - { - // No-op. - } - - Decimal::Decimal(int64_t val, int32_t scale) : - scale(scale), - magnitude(val) - { - // No-op. - } - - Decimal::Decimal(const BigInteger& val, int32_t scale) : - scale(scale), - magnitude(val) - { - // No-op. - } - - Decimal::Decimal(const char* val, int32_t len) : - scale(0), - magnitude(0) - { - AssignString(val, len); - } - - Decimal::~Decimal() - { - // No-op. - } - - Decimal& Decimal::operator=(const Decimal& other) - { - scale = other.scale; - magnitude = other.magnitude; - - return *this; - } - - Decimal::operator double() const - { - return ToDouble(); - } - - Decimal::operator int64_t() const - { - return ToInt64(); - } - - double Decimal::ToDouble() const - { - return common::LexicalCast(*this); - } - - int64_t Decimal::ToInt64() const - { - if (scale == 0) - return magnitude.ToInt64(); - - Decimal zeroScaled; - - SetScale(0, zeroScaled); - - return zeroScaled.magnitude.ToInt64(); - } - - int32_t Decimal::GetScale() const - { - return scale; - } - - void Decimal::SetScale(int32_t newScale, Decimal& res) const - { - if (scale == newScale) - return; - - int32_t diff = scale - newScale; - - BigInteger adjustment; - - if (diff > 0) - { - BigInteger::GetPowerOfTen(diff, adjustment); - - magnitude.Divide(adjustment, res.magnitude); - } - else - { - BigInteger::GetPowerOfTen(-diff, adjustment); - - magnitude.Multiply(adjustment, res.magnitude); - } - - res.scale = newScale; - } - - int32_t Decimal::GetPrecision() const - { - return magnitude.GetPrecision(); - } - - const BigInteger& Decimal::GetUnscaledValue() const - { - return magnitude; - } - - void Decimal::Swap(Decimal& second) - { - using std::swap; - - swap(scale, second.scale); - magnitude.Swap(second.magnitude); - } - - int32_t Decimal::GetMagnitudeLength() const - { - return magnitude.mag.GetSize(); - } - - void Decimal::AssignString(const char* val, int32_t len) - { - std::stringstream converter; - - converter.write(val, len); - - converter >> *this; - } - - void Decimal::AssignInt64(int64_t val) - { - magnitude.AssignInt64(val); - - scale = 0; - } - - void Decimal::AssignDouble(double val) - { - std::stringstream converter; - - converter.precision(16); - - converter << val; - converter >> *this; - } - - void Decimal::AssignUint64(uint64_t val) - { - magnitude.AssignUint64(val); - - scale = 0; - } - - int32_t Decimal::Compare(const Decimal& other) const - { - if (IsZero() && other.IsZero()) - return 0; - - if (scale == other.scale) - return magnitude.Compare(other.magnitude); - else if (scale > other.scale) - { - Decimal scaled; - - other.SetScale(scale, scaled); - - return magnitude.Compare(scaled.magnitude); - } - else - { - Decimal scaled; - - SetScale(other.scale, scaled); - - return scaled.magnitude.Compare(other.magnitude); - } - } - - bool Decimal::IsNegative() const - { - return magnitude.IsNegative(); - } - - bool Decimal::IsZero() const - { - return magnitude.IsZero(); - } - - bool Decimal::IsPositive() const - { - return magnitude.IsPositive(); - } - - bool operator==(const Decimal& val1, const Decimal& val2) - { - return val1.Compare(val2) == 0; - } - - bool operator!=(const Decimal& val1, const Decimal& val2) - { - return val1.Compare(val2) != 0; - } - - bool operator<(const Decimal& val1, const Decimal& val2) - { - return val1.Compare(val2) < 0; - } - - bool operator<=(const Decimal& val1, const Decimal& val2) - { - return val1.Compare(val2) <= 0; - } - - bool operator>(const Decimal& val1, const Decimal& val2) - { - return val1.Compare(val2) > 0; - } - - bool operator>=(const Decimal& val1, const Decimal& val2) - { - return val1.Compare(val2) >= 0; - } - } - } -} diff --git a/src/odbc/src/common/utils.cpp b/src/odbc/src/common/utils.cpp deleted file mode 100644 index 5dc44111f..000000000 --- a/src/odbc/src/common/utils.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -namespace ignite -{ - namespace odbc - { - namespace common - { - /** - * Check if string ends with the given ending. - * - * @param str String to check. - * @param ending Ending. - * @return Result. - */ - inline bool StringEndsWith(const std::string& str, const std::string& ending) - { - if (str.length() > ending.length()) - return str.compare(str.length() - ending.length(), ending.length(), ending) == 0; - - return false; - } - - void StripSurroundingWhitespaces(std::string& str) - { - std::string::size_type newBegin = 0; - while (newBegin < str.size() && ::isspace(str[newBegin])) - ++newBegin; - - if (newBegin == str.size()) - { - str.clear(); - - return; - } - - std::string::size_type newEnd = str.size() - 1; - while (::isspace(str[newEnd])) - --newEnd; - - str.assign(str, newBegin, (newEnd - newBegin) + 1); - } - - char* CopyChars(const char* val) - { - if (val) { - size_t len = strlen(val); - char* dest = new char[len + 1]; - strcpy(dest, val); - *(dest + len) = 0; - return dest; - } - - return 0; - } - - void ReleaseChars(char* val) - { - // Its OK to delete null-pointer. - delete[] val; - } - - uint32_t ToBigEndian(uint32_t value) - { - // The answer is 42 - static const int num = 42; - static const bool isLittleEndian = (*reinterpret_cast(&num) == num); - - if (isLittleEndian) - return ((value & 0xFF) << 24) | (((value >> 8) & 0xFF) << 16) | (((value >> 16) & 0xFF) << 8) | ((value >> 24) & 0xFF); - - return value; - } - - IGNITE_FRIEND_EXPORT Date MakeDateGmt(int year, int month, int day, int hour, - int min, int sec) - { - tm date; - - std::memset(&date, 0, sizeof(date)); - - date.tm_year = year - 1900; - date.tm_mon = month - 1; - date.tm_mday = day; - date.tm_hour = hour; - date.tm_min = min; - date.tm_sec = sec; - - return CTmToDate(date); - } - - IGNITE_FRIEND_EXPORT Date MakeDateLocal(int year, int month, int day, int hour, - int min, int sec) - { - tm date; - - std::memset(&date, 0, sizeof(date)); - - date.tm_year = year - 1900; - date.tm_mon = month - 1; - date.tm_mday = day; - date.tm_hour = hour; - date.tm_min = min; - date.tm_sec = sec; - - time_t localTime = common::IgniteTimeLocal(date); - - return CTimeToDate(localTime); - } - - IGNITE_FRIEND_EXPORT Time MakeTimeGmt(int hour, int min, int sec) - { - tm date; - - std::memset(&date, 0, sizeof(date)); - - date.tm_year = 70; - date.tm_mon = 0; - date.tm_mday = 1; - date.tm_hour = hour; - date.tm_min = min; - date.tm_sec = sec; - - return CTmToTime(date); - } - - IGNITE_FRIEND_EXPORT Time MakeTimeLocal(int hour, int min, int sec) - { - tm date; - - std::memset(&date, 0, sizeof(date)); - - date.tm_year = 70; - date.tm_mon = 0; - date.tm_mday = 1; - date.tm_hour = hour; - date.tm_min = min; - date.tm_sec = sec; - - time_t localTime = common::IgniteTimeLocal(date); - - return CTimeToTime(localTime); - } - - IGNITE_FRIEND_EXPORT Timestamp MakeTimestampGmt(int year, int month, int day, - int hour, int min, int sec, long ns) - { - tm date; - - std::memset(&date, 0, sizeof(date)); - - date.tm_year = year - 1900; - date.tm_mon = month - 1; - date.tm_mday = day; - date.tm_hour = hour; - date.tm_min = min; - date.tm_sec = sec; - - return CTmToTimestamp(date, ns); - } - - IGNITE_FRIEND_EXPORT Timestamp MakeTimestampLocal(int year, int month, int day, - int hour, int min, int sec, long ns) - { - tm date; - - std::memset(&date, 0, sizeof(date)); - - date.tm_year = year - 1900; - date.tm_mon = month - 1; - date.tm_mday = day; - date.tm_hour = hour; - date.tm_min = min; - date.tm_sec = sec; - - time_t localTime = common::IgniteTimeLocal(date); - - return CTimeToTimestamp(localTime, ns); - } - - IGNITE_IMPORT_EXPORT std::string GetDynamicLibraryName(const char* name) - { - std::stringstream libNameBuffer; - - libNameBuffer << name << Dle; - - return libNameBuffer.str(); - } - - IGNITE_IMPORT_EXPORT bool AllDigits(const std::string &val) - { - std::string::const_iterator i = val.begin(); - - while (i != val.end() && isdigit(*i)) - ++i; - - return i == val.end(); - } - - } - } -} diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index 09b0c0f71..b347c5035 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -21,7 +21,8 @@ #include #include -#include +#include + #include #include "ignite/odbc/log.h" @@ -35,10 +36,6 @@ #include "ignite/odbc/config/configuration.h" #include "ignite/odbc/config/connection_string_parser.h" #include "ignite/odbc/system/system_dsn.h" -#include "ignite/odbc/jni/java.h" -#include "ignite/odbc/jni/utils.h" -#include "ignite/odbc/common/concurrent.h" -#include "ignite/odbc/common/utils.h" // Uncomment for per-byte debug. //#define PER_BYTE_DEBUG @@ -60,16 +57,16 @@ namespace ignite { Connection::Connection(Environment* env) : env(env), + socket(), timeout(0), loginTimeout(DEFAULT_CONNECT_TIMEOUT), autoCommit(true), parser(), config(), info(config), - connection(), - opts() + streamingContext() { - // No-op + streamingContext.SetConnection(*this); } Connection::~Connection() @@ -146,15 +143,47 @@ namespace ignite IGNITE_ODBC_API_CALL(InternalEstablish(cfg)); } + SqlResult::Type Connection::InitSocket() + { + // Removed SSL Mode in DSN. Replaced this with REQUIRE for now. + ssl::SslMode::Type sslMode = ssl::SslMode::REQUIRE; + + if (sslMode == ssl::SslMode::DISABLE) + { + socket.reset(network::ssl::MakeTcpSocketClient()); + + return SqlResult::AI_SUCCESS; + } + + try + { + network::ssl::EnsureSslLoaded(); + } + catch (const IgniteError &err) + { + LOG_MSG("Can not load OpenSSL library: " << err.GetText()); + + AddStatusRecord("Can not load OpenSSL library (did you set OPENSSL_HOME environment variable?)"); + + return SqlResult::AI_ERROR; + } + + // Removed SSL key and cert files from DSN. Replaced with empty string for now. + socket.reset(network::ssl::MakeSecureSocketClient( + "", "", config.GetTlsCaFile())); + + return SqlResult::AI_SUCCESS; + } + SqlResult::Type Connection::InternalEstablish(const config::Configuration& cfg) { using ssl::SslMode; config = cfg; - if (connection) { - AddStatusRecord(SqlState::S08002_ALREADY_CONNECTED, - "Already connected."); + if (socket.get() != 0) + { + AddStatusRecord(SqlState::S08002_ALREADY_CONNECTED, "Already connected."); return SqlResult::AI_ERROR; } @@ -166,15 +195,11 @@ namespace ignite return SqlResult::AI_ERROR; } - odbc::IgniteError err; - bool connected = TryRestoreConnection(err); + bool connected = TryRestoreConnection(); if (!connected) { - std::string errMessage = "Failed to establish connection with the host.\n"; - errMessage.append(err.GetText()); - AddStatusRecord( - SqlState::S08001_CANNOT_CONNECT, errMessage); + AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "Failed to establish connection with the host."); return SqlResult::AI_ERROR; } @@ -196,7 +221,7 @@ namespace ignite SqlResult::Type Connection::InternalRelease() { - if (!connection) + if (socket.get() == 0) { AddStatusRecord(SqlState::S08003_NOT_CONNECTED, "Connection is not open."); @@ -212,19 +237,12 @@ namespace ignite void Connection::Close() { - if (connection) { - using namespace jni::java; - using namespace common::concurrent; - SharedPointer< JniContext > ctx(JniContext::Create(&opts[0], static_cast(opts.size()), JniHandlers())); - JniErrorInfo errInfo; - // NOTE: DocumentDbDisconnect will notify JNI connection is no longer used - must set to nullptr. - ctx.Get()->DocumentDbDisconnect(connection, &errInfo); - if (errInfo.code != java::IGNITE_JNI_ERR_SUCCESS) { - // TODO: Determine if we need to error check the close. - } - connection = nullptr; + if (socket.get() != 0) + { + socket->Close(); + + socket.reset(); } - Deinit(); } Statement* Connection::CreateStatement() @@ -252,26 +270,125 @@ namespace ignite bool Connection::Send(const int8_t* data, size_t len, int32_t timeout) { - // TODO: Remove if unnecessary + if (socket.get() == 0) + throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established"); + + int32_t newLen = static_cast(len + sizeof(OdbcProtocolHeader)); + + common::FixedSizeArray msg(newLen); + + OdbcProtocolHeader *hdr = reinterpret_cast(msg.GetData()); + + hdr->len = static_cast(len); + + memcpy(msg.GetData() + sizeof(OdbcProtocolHeader), data, len); + + OperationResult::T res = SendAll(msg.GetData(), msg.GetSize(), timeout); + + if (res == OperationResult::TIMEOUT) + return false; + + if (res == OperationResult::FAIL) + throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not send message due to connection failure"); + +#ifdef PER_BYTE_DEBUG + LOG_MSG("message sent: (" << msg.GetSize() << " bytes)" << utility::HexDump(msg.GetData(), msg.GetSize())); +#endif //PER_BYTE_DEBUG + return true; } Connection::OperationResult::T Connection::SendAll(const int8_t* data, size_t len, int32_t timeout) { - // TODO: Remove if unnecessary. - // No-op + int sent = 0; + + while (sent != static_cast(len)) + { + int res = socket->Send(data + sent, len - sent, timeout); + + LOG_MSG("Sent: " << res); + + if (res < 0 || res == network::SocketClient::WaitResult::TIMEOUT) + { + Close(); + + return res < 0 ? OperationResult::FAIL : OperationResult::TIMEOUT; + } + + sent += res; + } + + assert(static_cast(sent) == len); + return OperationResult::SUCCESS; } bool Connection::Receive(std::vector& msg, int32_t timeout) { - // TODO: Remove if unnecessary. + if (socket.get() == 0) + throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established"); + + msg.clear(); + + OdbcProtocolHeader hdr; + + OperationResult::T res = ReceiveAll(reinterpret_cast(&hdr), sizeof(hdr), timeout); + + if (res == OperationResult::TIMEOUT) + return false; + + if (res == OperationResult::FAIL) + throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not receive message header"); + + if (hdr.len < 0) + { + Close(); + + throw OdbcError(SqlState::SHY000_GENERAL_ERROR, "Protocol error: Message length is negative"); + } + + if (hdr.len == 0) + return false; + + msg.resize(hdr.len); + + res = ReceiveAll(&msg[0], hdr.len, timeout); + + if (res == OperationResult::TIMEOUT) + return false; + + if (res == OperationResult::FAIL) + throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not receive message body"); + +#ifdef PER_BYTE_DEBUG + LOG_MSG("Message received: " << utility::HexDump(&msg[0], msg.size())); +#endif //PER_BYTE_DEBUG + return true; } Connection::OperationResult::T Connection::ReceiveAll(void* dst, size_t len, int32_t timeout) { - // TODO: Remove if unnecessary. + size_t remain = len; + int8_t* buffer = reinterpret_cast(dst); + + while (remain) + { + size_t received = len - remain; + + int res = socket->Receive(buffer + received, remain, timeout); + LOG_MSG("Receive res: " << res << " remain: " << remain); + + if (res < 0 || res == network::SocketClient::WaitResult::TIMEOUT) + { + Close(); + + return res < 0 ? OperationResult::FAIL : OperationResult::TIMEOUT; + } + + remain -= static_cast(res); + } + return OperationResult::SUCCESS; } @@ -327,7 +444,7 @@ namespace ignite return SqlResult::AI_ERROR; } - catch (const odbc::IgniteError& err) + catch (const IgniteError& err) { AddStatusRecord(err.GetText()); @@ -368,7 +485,7 @@ namespace ignite return SqlResult::AI_ERROR; } - catch (const odbc::IgniteError& err) + catch (const IgniteError& err) { AddStatusRecord(err.GetText()); @@ -398,7 +515,7 @@ namespace ignite { SQLUINTEGER *val = reinterpret_cast(buf); - *val = connection ? SQL_CD_FALSE : SQL_CD_TRUE; + *val = socket.get() != 0 ? SQL_CD_FALSE : SQL_CD_TRUE; if (valueLen) *valueLen = SQL_IS_INTEGER; @@ -563,7 +680,7 @@ namespace ignite return SqlResult::AI_ERROR; } - catch (const odbc::IgniteError& err) + catch (const IgniteError& err) { AddStatusRecord(SqlState::S08004_CONNECTION_REJECTED, err.GetText()); @@ -598,177 +715,67 @@ namespace ignite void Connection::EnsureConnected() { - if (connection) + if (socket.get() != 0) return; - odbc::IgniteError err; - bool success = TryRestoreConnection(err); + bool success = TryRestoreConnection(); if (!success) throw OdbcError(SqlState::S08001_CANNOT_CONNECT, "Failed to establish connection with any provided hosts"); } - bool Connection::TryRestoreConnection(odbc::IgniteError& err) + bool Connection::TryRestoreConnection() { - bool connected = false; + std::vector addrs; - using namespace jni::java; - using namespace common::concurrent; + CollectAddresses(config, addrs); + + if (socket.get() == 0) + { + SqlResult::Type res = InitSocket(); - if (connection) { - return true; + if (res != SqlResult::AI_SUCCESS) + return false; } - std::string connectionString = FormatJdbcConnectionString(); - JniErrorInfo errInfo; + bool connected = false; - std::string docdb_home = common::GetEnv("DOCUMENTDB_HOME") - + "\\documentdb-jdbc-1.1.0-all.jar"; - - // 2. Resolve DOCUMENTDB_HOME. - std::string home = jni::ResolveDocumentDbHome(); + while (!addrs.empty() && !connected) + { + const EndPoint& addr = addrs.back(); - // 3. Create classpath. - std::string cp = jni::CreateDocumentDbClasspath(std::string(), home); + for (uint16_t port = addr.port; port <= addr.port + addr.range; ++port) + { + try + { + connected = socket->Connect(addr.host.c_str(), port, loginTimeout); + } + catch (const IgniteError& err) + { + LOG_MSG("Error while trying connect to " << addr.host << ":" << addr.port <<", " << err.GetText()); + } - if (cp.empty()) { - err = - odbc::IgniteError(odbc::IgniteError::IGNITE_ERR_JVM_NO_CLASSPATH, - "Java classpath is empty (did you set " - "DOCUMENTDB_HOME environment variable?)"); + if (connected) + { + SqlResult::Type res = MakeRequestHandshake(); - return false; - } + connected = res != SqlResult::AI_ERROR; - SetJvmOptions(cp); - - SharedPointer< JniContext > ctx(JniContext::Create(&opts[0], static_cast(opts.size()), JniHandlers(), &errInfo)); - if (ctx.Get()) { - jobject result = ctx.Get()->DocumentDbConnect( - connectionString.c_str(), &errInfo); - connected = (result && errInfo.code == java::IGNITE_JNI_ERR_SUCCESS); - if (!connected) { - err = odbc::IgniteError( - odbc::IgniteError::IGNITE_ERR_SECURE_CONNECTION_FAILURE, - errInfo.errMsg); - Close(); + if (connected) + break; + } } - connection = result; - } else { - err = odbc::IgniteError(odbc::IgniteError::IGNITE_ERR_JVM_INIT, "Unable to get initialized JVM."); - connection = nullptr; + + addrs.pop_back(); } + if (!connected) + Close(); + return connected; } - std::string Connection::FormatJdbcConnectionString() const { - std::string host = "localhost"; - std::string port = "27017"; - if (!config.GetAddresses().empty()) { - host = config.GetAddresses()[0].host; - port = std::to_string(config.GetAddresses()[0].port); - } - std::string jdbConnectionString; - - jdbConnectionString = "jdbc:documentdb:"; - jdbConnectionString.append("//" + config.GetUser()); - jdbConnectionString.append(":" + config.GetPassword()); - jdbConnectionString.append("@" + host); - jdbConnectionString.append(":" + port); - jdbConnectionString.append("/" + config.GetSchema()); - jdbConnectionString.append("?tlsAllowInvalidHostnames=true"); - - // Check if internal SSH tunnel should be enabled. - // TODO: Remove use of environment variables and use DSN properties - std::string sshUserAtHost = common::GetEnv("DOC_DB_USER", ""); - std::string sshRemoteHost = common::GetEnv("DOC_DB_HOST", ""); - std::string sshPrivKeyFile = common::GetEnv("DOC_DB_PRIV_KEY_FILE", ""); - std::string sshUser; - std::string sshTunnelHost; - size_t indexOfAt = sshUserAtHost.find_first_of('@'); - if (indexOfAt >= 0 && sshUserAtHost.size() > (indexOfAt + 1)) { - sshUser = sshUserAtHost.substr(0, indexOfAt); - sshTunnelHost = sshUserAtHost.substr(indexOfAt + 1); - } - if (!sshUserAtHost.empty() - && !sshRemoteHost.empty() - && !sshPrivKeyFile.empty() - && !sshUser.empty() - && !sshTunnelHost.empty()) { - jdbConnectionString.append("&sshUser=" + sshUser); - jdbConnectionString.append("&sshHost=" + sshTunnelHost); - jdbConnectionString.append("&sshPrivateKeyFile=" + sshPrivKeyFile); - jdbConnectionString.append("&sshStrictHostKeyChecking=false"); - } - - return jdbConnectionString; - } - - /** - * Create JVM options from configuration. - * - * @param cfg Configuration. - * @param home Optional GG home. - * @param cp Classpath. - */ - void Connection::SetJvmOptions(const std::string& cp) { - using namespace common; - Deinit(); - - const size_t REQ_OPTS_CNT = 4; - const size_t JAVA9_OPTS_CNT = 6; - - opts.reserve(REQ_OPTS_CNT + JAVA9_OPTS_CNT); - - // 1. Set classpath. - std::string cpFull = "-Djava.class.path=" + cp; - - opts.push_back(CopyChars(cpFull.c_str())); - - // 3. Set Xms, Xmx. - std::string xmsStr = "-Xms" + std::to_string(256) + "m"; - std::string xmxStr = "-Xmx" + std::to_string(1024) + "m"; - - opts.push_back(CopyChars(xmsStr.c_str())); - opts.push_back(CopyChars(xmxStr.c_str())); - - // 4. Optional debug arguments - //std::string debugStr = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"; - //opts.push_back(CopyChars(debugStr.c_str())); - - // 5. Set file.encoding. - std::string fileEncParam = "-Dfile.encoding="; - std::string fileEncFull = fileEncParam + "UTF-8"; - opts.push_back(CopyChars(fileEncFull.c_str())); - - // Adding options for Java 9 or later - if (jni::java::IsJava9OrLater()) { - opts.push_back(CopyChars( - "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-exports=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-exports=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED")); - } - } - - /** - * Deallocates all allocated data. - */ - void Connection::Deinit() { - using namespace common; - std::for_each(opts.begin(), opts.end(), ReleaseChars); - opts.clear(); - } - void Connection::CollectAddresses(const config::Configuration& cfg, std::vector& endPoints) { endPoints.clear(); @@ -798,6 +805,14 @@ namespace ignite { SQLUINTEGER uTimeout = static_cast(reinterpret_cast(value)); + if (uTimeout != 0 && socket.get() != 0 && socket->IsBlocking()) + { + AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, "Can not set timeout, because can not " + "enable non-blocking mode on TCP connection. Setting to 0."); + + return 0; + } + if (uTimeout > INT32_MAX) { std::stringstream ss; diff --git a/src/odbc/src/ignite_error.cpp b/src/odbc/src/ignite_error.cpp deleted file mode 100644 index 23841d413..000000000 --- a/src/odbc/src/ignite_error.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include - -#include -#include - -using namespace ignite::odbc::common; -using namespace ignite::odbc::java; - -namespace ignite -{ - namespace odbc - { - void IgniteError::ThrowIfNeeded(const IgniteError& err) - { - if (err.code != IGNITE_SUCCESS) - throw err; - } - - IgniteError::IgniteError() : - code(IGNITE_SUCCESS), - msg(NULL) - { - // No-op. - } - - IgniteError::IgniteError(int32_t code) : - code(code), - msg(NULL) - { - } - - IgniteError::IgniteError(int32_t code, const char* msg) : - code(code), - msg(CopyChars(msg)) - { - // No-op. - } - - IgniteError::IgniteError(const IgniteError& other) : - code(other.code), - msg(CopyChars(other.msg)) - { - // No-op. - } - - IgniteError& IgniteError::operator=(const IgniteError& other) - { - if (this != &other) - { - IgniteError tmp(other); - - std::swap(code, tmp.code); - std::swap(msg, tmp.msg); - } - - return *this; - } - - IgniteError::~IgniteError() IGNITE_NO_THROW - { - ReleaseChars(msg); - } - - int32_t IgniteError::GetCode() const - { - return code; - } - - const char* IgniteError::GetText() const IGNITE_NO_THROW - { - if (code == IGNITE_SUCCESS) - return "Operation completed successfully."; - else if (msg) - return msg; - else - return "No additional information available."; - } - - const char* IgniteError::what() const IGNITE_NO_THROW - { - return GetText(); - } - - void IgniteError::SetError(const int jniCode, const char* jniCls, const char* jniMsg, IgniteError& err) - { - if (jniCode == IGNITE_JNI_ERR_SUCCESS) - err = IgniteError(); - else if (jniCode == IGNITE_JNI_ERR_GENERIC) - { - // The most common case when we have Java exception "in hands" and must map it to respective code. - if (jniCls) - { - std::string jniCls0 = jniCls; - - if (jniCls0.compare("java.lang.NoClassDefFoundError") == 0) - { - std::stringstream stream; - - stream << "Java class is not found (did you set DOCUMENTDB_HOME environment variable?)"; - - if (jniMsg) - stream << ": " << jniMsg; - - err = IgniteError(IGNITE_ERR_JVM_NO_CLASS_DEF_FOUND, stream.str().c_str()); - } - else if (jniCls0.compare("java.lang.NoSuchMethodError") == 0) - { - std::stringstream stream; - - stream << "Java method is not found (did you set DOCUMENTDB_HOME environment variable?)"; - - if (jniMsg) - stream << ": " << jniMsg; - - err = IgniteError(IGNITE_ERR_JVM_NO_SUCH_METHOD, stream.str().c_str()); - } - else if (jniCls0.compare("java.lang.IllegalArgumentException") == 0) - err = IgniteError(IGNITE_ERR_ILLEGAL_ARGUMENT, jniMsg); - else if (jniCls0.compare("java.lang.IllegalStateException") == 0) - err = IgniteError(IGNITE_ERR_ILLEGAL_STATE, jniMsg); - else if (jniCls0.compare("java.lang.UnsupportedOperationException") == 0) - err = IgniteError(IGNITE_ERR_UNSUPPORTED_OPERATION, jniMsg); - else if (jniCls0.compare("java.lang.InterruptedException") == 0) - err = IgniteError(IGNITE_ERR_INTERRUPTED, jniMsg); - else if (jniCls0.compare("org.apache.ignite.cluster.ClusterGroupEmptyException") == 0) - err = IgniteError(IGNITE_ERR_CLUSTER_GROUP_EMPTY, jniMsg); - else if (jniCls0.compare("org.apache.ignite.cluster.ClusterTopologyException") == 0) - err = IgniteError(IGNITE_ERR_CLUSTER_TOPOLOGY, jniMsg); - else if (jniCls0.compare("org.apache.ignite.compute.ComputeExecutionRejectedException") == 0) - err = IgniteError(IGNITE_ERR_COMPUTE_EXECUTION_REJECTED, jniMsg); - else if (jniCls0.compare("org.apache.ignite.compute.ComputeJobFailoverException") == 0) - err = IgniteError(IGNITE_ERR_COMPUTE_JOB_FAILOVER, jniMsg); - else if (jniCls0.compare("org.apache.ignite.compute.ComputeTaskCancelledException") == 0) - err = IgniteError(IGNITE_ERR_COMPUTE_TASK_CANCELLED, jniMsg); - else if (jniCls0.compare("org.apache.ignite.compute.ComputeTaskTimeoutException") == 0) - err = IgniteError(IGNITE_ERR_COMPUTE_TASK_TIMEOUT, jniMsg); - else if (jniCls0.compare("org.apache.ignite.compute.ComputeUserUndeclaredException") == 0) - err = IgniteError(IGNITE_ERR_COMPUTE_USER_UNDECLARED_EXCEPTION, jniMsg); - else if (jniCls0.compare("javax.cache.CacheException") == 0) - err = IgniteError(IGNITE_ERR_CACHE, jniMsg); - else if (jniCls0.compare("javax.cache.integration.CacheLoaderException") == 0) - err = IgniteError(IGNITE_ERR_CACHE_LOADER, jniMsg); - else if (jniCls0.compare("javax.cache.integration.CacheWriterException") == 0) - err = IgniteError(IGNITE_ERR_CACHE_WRITER, jniMsg); - else if (jniCls0.compare("javax.cache.processor.EntryProcessorException") == 0) - err = IgniteError(IGNITE_ERR_ENTRY_PROCESSOR, jniMsg); - else if (jniCls0.compare("org.apache.ignite.cache.CachePartialUpdateException") == 0) - err = IgniteError(IGNITE_ERR_CACHE_PARTIAL_UPDATE, jniMsg); - else if (jniCls0.compare("org.apache.ignite.transactions.TransactionOptimisticException") == 0) - err = IgniteError(IGNITE_ERR_TX_OPTIMISTIC, jniMsg); - else if (jniCls0.compare("org.apache.ignite.transactions.TransactionTimeoutException") == 0) - err = IgniteError(IGNITE_ERR_TX_TIMEOUT, jniMsg); - else if (jniCls0.compare("org.apache.ignite.transactions.TransactionRollbackException") == 0) - err = IgniteError(IGNITE_ERR_TX_ROLLBACK, jniMsg); - else if (jniCls0.compare("org.apache.ignite.transactions.TransactionHeuristicException") == 0) - err = IgniteError(IGNITE_ERR_TX_HEURISTIC, jniMsg); - else if (jniCls0.compare("org.apache.ignite.IgniteAuthenticationException") == 0) - err = IgniteError(IGNITE_ERR_AUTHENTICATION, jniMsg); - else if (jniCls0.compare("org.apache.ignite.plugin.security.GridSecurityException") == 0) - err = IgniteError(IGNITE_ERR_SECURITY, jniMsg); - else if (jniCls0.compare("org.apache.ignite.IgniteException") == 0) - err = IgniteError(IGNITE_ERR_GENERIC, jniMsg); - else if (jniCls0.compare("org.apache.ignite.IgniteCheckedException") == 0) - err = IgniteError(IGNITE_ERR_GENERIC, jniMsg); - else - { - std::stringstream stream; - - stream << "Java exception occurred [cls=" << jniCls0; - - if (jniMsg) - stream << ", msg=" << jniMsg; - - stream << "]"; - - err = IgniteError(IGNITE_ERR_UNKNOWN, stream.str().c_str()); - } - } - else - { - // JNI class name is not available. Something really weird. - err = IgniteError(IGNITE_ERR_UNKNOWN); - } - } - else if (jniCode == IGNITE_JNI_ERR_JVM_INIT) - { - std::stringstream stream; - - stream << "Failed to initialize JVM [errCls="; - - if (jniCls) - stream << jniCls; - else - stream << "N/A"; - - stream << ", errMsg="; - - if (jniMsg) - stream << jniMsg; - else - stream << "N/A"; - - stream << "]"; - - err = IgniteError(IGNITE_ERR_JVM_INIT, stream.str().c_str()); - } - else if (jniCode == IGNITE_JNI_ERR_JVM_ATTACH) - err = IgniteError(IGNITE_ERR_JVM_ATTACH, "Failed to attach to JVM."); - } - } -} diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp deleted file mode 100644 index dcd21b0b3..000000000 --- a/src/odbc/src/jni/java.cpp +++ /dev/null @@ -1,1102 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// ReSharper disable once CppUnusedIncludeDirective -#include // needed only on linux -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifndef JNI_VERSION_9 -#define JNI_VERSION_9 0x00090000 -#endif // JNI_VERSION_9 - -#define IGNITE_SAFE_PROC_NO_ARG(jniEnv, envPtr, type, field) { \ - JniHandlers* hnds = reinterpret_cast(envPtr); \ - type hnd = hnds->field; \ - if (hnd) \ - { \ - try \ - { \ - hnd(hnds->target); \ - } \ - catch (std::exception& err) \ - { \ - ThrowToJava(jniEnv, err.what()); \ - } \ - } \ - else \ - ThrowOnMissingHandler(jniEnv); \ -} - -#define IGNITE_SAFE_PROC(jniEnv, envPtr, type, field, ...) { \ - JniHandlers* hnds = reinterpret_cast(envPtr); \ - type hnd = hnds->field; \ - if (hnd) \ - { \ - try \ - { \ - hnd(hnds->target, __VA_ARGS__); \ - } \ - catch (std::exception& err) \ - { \ - ThrowToJava(jniEnv, err.what()); \ - } \ - } \ - else \ - ThrowOnMissingHandler(jniEnv); \ -} - -#define IGNITE_SAFE_FUNC(jniEnv, envPtr, type, field, ...) { \ - JniHandlers* hnds = reinterpret_cast(envPtr); \ - type hnd = hnds->field; \ - if (hnd) \ - { \ - try \ - { \ - return hnd(hnds->target, __VA_ARGS__); \ - } \ - catch (std::exception& err) \ - { \ - ThrowToJava(jniEnv, err.what()); \ - return 0; \ - } \ - } \ - else \ - { \ - ThrowOnMissingHandler(jniEnv); \ - return 0; \ - }\ -} - -using namespace ignite::odbc::java; - -namespace ignite -{ - namespace odbc - { - namespace jni - { - namespace java - { - namespace iocc = ignite::odbc::common::concurrent; - - bool IGNITE_IMPORT_EXPORT IsJava9OrLater() - { - JavaVMInitArgs args; - - memset(&args, 0, sizeof(args)); - - args.version = JNI_VERSION_9; - - return JNI_GetDefaultJavaVMInitArgs(&args) == JNI_OK; - } - - /* --- Startup exception. --- */ - class JvmException : public std::exception { - // No-op. - }; - - /* --- JNI method definitions. --- */ - struct JniMethod { - char* name; - char* sign; - bool isStatic; - - JniMethod(const char* name, const char* sign, bool isStatic) - : name(const_cast< char* >(name)), - sign(const_cast< char* >(sign)), - isStatic(isStatic) { - } - }; - - JniErrorInfo::JniErrorInfo() : code(IGNITE_JNI_ERR_SUCCESS) - { - // No-op. - } - - JniErrorInfo::JniErrorInfo(int code, const char* errCls, const char* errMsg) : code(code) - { - this->errCls = common::CopyChars(errCls); - this->errMsg = common::CopyChars(errMsg); - } - - JniErrorInfo::JniErrorInfo(const JniErrorInfo& other) : code(other.code) - { - this->errCls = common::CopyChars(other.errCls); - this->errMsg = common::CopyChars(other.errMsg); - } - - JniErrorInfo& JniErrorInfo::operator=(const JniErrorInfo& other) - { - if (this != &other) - { - // 1. Create new instance, exception could occur at this point. - JniErrorInfo tmp(other); - - // 2. Swap with temp. - std::swap(code, tmp.code); - std::swap(errCls, tmp.errCls); - std::swap(errMsg, tmp.errMsg); - } - - return *this; - } - - JniErrorInfo::~JniErrorInfo() - { - delete[] errCls; - delete[] errMsg; - } - - /** - * Guard to ensure global reference cleanup. - */ - class JniGlobalRefGuard - { - public: - JniGlobalRefGuard(JNIEnv *e, jobject obj) : env(e), ref(obj) - { - // No-op. - } - - ~JniGlobalRefGuard() - { - env->DeleteGlobalRef(ref); - } - - private: - /** Environment. */ - JNIEnv* env; - - /** Target reference. */ - jobject ref; - - IGNITE_NO_COPY_ASSIGNMENT(JniGlobalRefGuard); - }; - - const char* C_THROWABLE = "java/lang/Throwable"; - JniMethod M_THROWABLE_GET_MESSAGE = JniMethod("getMessage", "()Ljava/lang/String;", false); - JniMethod M_THROWABLE_PRINT_STACK_TRACE = JniMethod("printStackTrace", "()V", false); - - const char* C_CLASS = "java/lang/Class"; - JniMethod M_CLASS_GET_NAME = JniMethod("getName", "()Ljava/lang/String;", false); - - const char* C_DOCUMENTDB_CONNECTION_PROPERTIES = - "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; - JniMethod M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING = - JniMethod( - "getPropertiesFromConnectionString", - "(Ljava/lang/String;)Lsoftware/amazon/documentdb/jdbc/DocumentDbConnectionProperties;", - true); - - const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; - - const char* C_DRIVERMANAGER = "java/sql/DriverManager"; - JniMethod M_DRIVERMANAGER_GET_CONNECTION = - JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); - - const char* C_JAVA_SQL_CONNECTION = "java/sql/Connection"; - JniMethod M_JAVA_SQL_CONNECTION_CLOSE = JniMethod("close", "()V", false); - - // TODO: Provide a "getFullStackTrace" from DocumentDB - //JniMethod M_PLATFORM_UTILS_GET_FULL_STACK_TRACE = JniMethod("getFullStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;", true); - - - /* STATIC STATE. */ - iocc::CriticalSection JVM_LOCK; - iocc::CriticalSection CONSOLE_LOCK; - JniJvm JVM; - bool PRINT_EXCEPTION = false; - std::vector consoleWriteHandlers; - - /* HELPER METHODS. */ - - /** - * Throw exception to Java in case of missing callback pointer. It means that callback is not implemented in - * native platform and Java -> platform operation cannot proceede further. As JniContext is not available at - * this point, we have to obtain exception details from scratch. This is not critical from performance - * perspective because missing handler usually denotes fatal condition. - * - * @param env JNI environment. - */ - int ThrowOnMissingHandler(JNIEnv* env) - { - //jclass cls = env->FindClass(C_PLATFORM_NO_CALLBACK_EXCEPTION); - - //env->ThrowNew(cls, "Callback handler is not set in native platform."); - - return 0; - } - - /** - * Throw generic exception to Java in case of native exception. As JniContext is not available at - * this point, we have to obtain exception details from scratch. This is not critical from performance - * perspective because such exception is usually denotes fatal condition. - * - * @param env JNI environment. - * @param msg Message. - */ - void ThrowToJava(JNIEnv* env, const char* msg) - { - //jclass cls = env->FindClass(C_IGNITE_EXCEPTION); - - //env->ThrowNew(cls, msg); - } - - char* StringToChars(JNIEnv* env, jstring str, int* len) { - if (!str) { - *len = 0; - return NULL; - } - - const char* strChars = env->GetStringUTFChars(str, 0); - const int strCharsLen = env->GetStringUTFLength(str); - - char* strChars0 = new char[strCharsLen + 1]; - std::strcpy(strChars0, strChars); - *(strChars0 + strCharsLen) = 0; - - env->ReleaseStringUTFChars(str, strChars); - - if (len) - *len = strCharsLen; - - return strChars0; - } - - std::string JavaStringToCString(JNIEnv* env, jstring str, int* len) - { - char* resChars = StringToChars(env, str, len); - - if (resChars) - { - std::string res = std::string(resChars, *len); - - delete[] resChars; - - return res; - } - else - return std::string(); - } - - jclass FindClass(JNIEnv* env, const char *name) { - jclass res = env->FindClass(name); - - if (!res) - throw JvmException(); - - jclass res0 = static_cast(env->NewGlobalRef(res)); - - env->DeleteLocalRef(res); - - return res0; - } - - void DeleteClass(JNIEnv* env, jclass cls) { - if (cls) - env->DeleteGlobalRef(cls); - } - - void CheckClass(JNIEnv* env, const char *name) - { - jclass res = env->FindClass(name); - - if (!res) - throw JvmException(); - } - - jmethodID FindMethod(JNIEnv* env, jclass cls, JniMethod mthd) { - jmethodID mthd0 = mthd.isStatic - ? env->GetStaticMethodID(cls, mthd.name, mthd.sign) - : env->GetMethodID(cls, mthd.name, mthd.sign); - - if (!mthd0) - throw JvmException(); - - return mthd0; - } - - jobject NewObject(JNIEnv* env, jclass clazz, jmethodID constructor, ...) { - va_list args; - va_start(args, constructor); - jobject result = env->NewObject(clazz, constructor, args); - va_end(args); - - if (!result) - throw JvmException(); - - return result; - } - - void AddNativeMethod(JNINativeMethod* mthd, JniMethod jniMthd, void* fnPtr) { - mthd->name = jniMthd.name; - mthd->signature = jniMthd.sign; - mthd->fnPtr = fnPtr; - } - - void JniJavaMembers::Initialize(JNIEnv* env) { - c_Class = FindClass(env, C_CLASS); - m_Class_getName = FindMethod(env, c_Class, M_CLASS_GET_NAME); - - c_Throwable = FindClass(env, C_THROWABLE); - m_Throwable_getMessage = FindMethod(env, c_Throwable, M_THROWABLE_GET_MESSAGE); - m_Throwable_printStackTrace = FindMethod(env, c_Throwable, M_THROWABLE_PRINT_STACK_TRACE); - - // TODO: Provide "getFullStackTrace" in DocumentDB - //m_PlatformUtils_getFullStackTrace = FindMethod(env, c_PlatformUtils, M_PLATFORM_UTILS_GET_FULL_STACK_TRACE); - } - - void JniJavaMembers::Destroy(JNIEnv* env) { - DeleteClass(env, c_Class); - DeleteClass(env, c_Throwable); - DeleteClass(env, c_PlatformUtils); - } - - bool JniJavaMembers::WriteErrorInfo(JNIEnv* env, char** errClsName, int* errClsNameLen, char** errMsg, - int* errMsgLen, char** stackTrace, int* stackTraceLen) { - if (env && env->ExceptionCheck()) { - if (m_Class_getName && m_Throwable_getMessage) { - jthrowable err = env->ExceptionOccurred(); - - env->ExceptionClear(); - - jclass errCls = env->GetObjectClass(err); - - jstring clsName = static_cast(env->CallObjectMethod(errCls, m_Class_getName)); - *errClsName = StringToChars(env, clsName, errClsNameLen); - - jstring msg = static_cast(env->CallObjectMethod(err, m_Throwable_getMessage)); - *errMsg = StringToChars(env, msg, errMsgLen); - - jstring trace = NULL; - - if (c_PlatformUtils && m_PlatformUtils_getFullStackTrace) { - trace = static_cast(env->CallStaticObjectMethod(c_PlatformUtils, m_PlatformUtils_getFullStackTrace, err)); - *stackTrace = StringToChars(env, trace, stackTraceLen); - } - - if (errCls) - env->DeleteLocalRef(errCls); - - if (clsName) - env->DeleteLocalRef(clsName); - - if (msg) - env->DeleteLocalRef(msg); - - if (trace) - env->DeleteLocalRef(trace); - - return true; - } - else { - env->ExceptionClear(); - } - } - - return false; - } - - void JniMembers::Initialize(JNIEnv* env) { - c_DocumentDbConnectionProperties = FindClass(env, C_DOCUMENTDB_CONNECTION_PROPERTIES); - m_DocumentDbConnectionPropertiesGetPropertiesFromConnectionString = - FindMethod(env, c_DocumentDbConnectionProperties, M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING); - - c_DocumentDbConnection = FindClass(env, C_DOCUMENTDB_CONNECTION); - //m_DocumentDbConnectionInit = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_PROPERTIES_INIT); - - c_DriverManager = FindClass(env, C_DRIVERMANAGER); - m_DriverManagerGetConnection = FindMethod(env, c_DriverManager, M_DRIVERMANAGER_GET_CONNECTION); - - c_JavaSqlConnection = FindClass(env, C_JAVA_SQL_CONNECTION); - m_JavaSqlConnectionClose = FindMethod(env, c_JavaSqlConnection, M_JAVA_SQL_CONNECTION_CLOSE); - } - - void JniMembers::Destroy(JNIEnv* env) { - DeleteClass(env, c_IgniteException); - DeleteClass(env, c_PlatformIgnition); - DeleteClass(env, c_PlatformTarget); - DeleteClass(env, c_PlatformUtils); - } - - JniJvm::JniJvm() : jvm(NULL), javaMembers(JniJavaMembers()), members(JniMembers()) - { - // No-op. - } - - JniJvm::JniJvm(JavaVM* jvm, JniJavaMembers javaMembers, JniMembers members) : - jvm(jvm), javaMembers(javaMembers), members(members) - { - // No-op. - } - - JavaVM* JniJvm::GetJvm() - { - return jvm; - } - - JniJavaMembers& JniJvm::GetJavaMembers() - { - return javaMembers; - } - - JniMembers& JniJvm::GetMembers() - { - return members; - } - - /** - * Create JVM. - */ - jint GetOrCreateJvm(char** opts, int optsLen, JavaVM** jvm, JNIEnv** env) { - // Check to see if a VM is already created - const jsize nJvms = 1; - jsize nJvmsAvailable = 0; - JavaVM* availableJvms[nJvms]{}; - jint res = JNI_GetCreatedJavaVMs(&availableJvms[0], nJvms, - &nJvmsAvailable); - if (res == JNI_OK && nJvmsAvailable >= 1) { - *jvm = availableJvms[0]; - res = (*jvm)->GetEnv(reinterpret_cast< void** >(env), - JNI_VERSION_1_8); - if (res == JNI_OK) { - return res; - } - } - - // Otherwise, create a VM - JavaVMOption* opts0 = new JavaVMOption[optsLen]; - - for (int i = 0; i < optsLen; i++) - opts0[i].optionString = *(opts + i); - - JavaVMInitArgs args{}; - args.version = JNI_VERSION_1_8; - args.nOptions = optsLen; - args.options = opts0; - args.ignoreUnrecognized = 0; - - res = JNI_CreateJavaVM(jvm, reinterpret_cast(env), &args); - - delete[] opts0; - - return res; - } - - void RegisterNatives(JNIEnv* env) { - { - JNINativeMethod methods[5]; - - int idx = 0; - - // TODO: Investigate registering callbacks to get console and logging streams. - - //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_CONSOLE_WRITE, reinterpret_cast(JniConsoleWrite)); - - //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_LOG, reinterpret_cast(JniLoggerLog)); - //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_IS_LEVEL_ENABLED, reinterpret_cast(JniLoggerIsLevelEnabled)); - - //jint res = env->RegisterNatives(FindClass(env, C_PLATFORM_CALLBACK_UTILS), methods, idx); - - //if (res != JNI_OK) - // throw JvmException(); - } - } - - JniContext::JniContext(JniJvm* jvm, JniHandlers hnds) : jvm(jvm), hnds(hnds) { - // No-op. - } - - JniContext* JniContext::Create(char** opts, int optsLen, JniHandlers hnds) { - return Create(opts, optsLen, hnds, NULL); - } - - void GetJniErrorMessage(std::string& errMsg, jint res) - { - switch (res) - { - case JNI_ERR: - errMsg = "Unknown error (JNI_ERR)."; - break; - - case JNI_EDETACHED: - errMsg = "Thread detached from the JVM."; - break; - - case JNI_EVERSION: - errMsg = "JNI version error."; - break; - - case JNI_ENOMEM: - errMsg = "Could not reserve enough space for object heap. Check Xmx option."; - break; - - case JNI_EEXIST: - errMsg = "JVM already created."; - break; - - case JNI_EINVAL: - errMsg = "Invalid JVM arguments."; - break; - - default: - errMsg = "Unexpected JNI_CreateJavaVM result."; - break; - } - } - - JniContext* JniContext::Create(char** opts, int optsLen, JniHandlers hnds, JniErrorInfo* errInfo) - { - // Acquire global lock to instantiate the JVM. - JVM_LOCK.Enter(); - - // Define local variables. - JavaVM* jvm = NULL; - JNIEnv* env = NULL; - - JniJavaMembers javaMembers; - memset(&javaMembers, 0, sizeof(javaMembers)); - - JniMembers members; - memset(&members, 0, sizeof(members)); - - JniContext* ctx = NULL; - - std::string errClsName; - int errClsNameLen = 0; - std::string errMsg; - int errMsgLen = 0; - std::string stackTrace; - int stackTraceLen = 0; - - try { - if (!JVM.GetJvm()) - { - // 1. Create JVM itself. - jint res = GetOrCreateJvm(opts, optsLen, &jvm, &env); - - if (res == JNI_OK) - { - // 2. Populate members; - javaMembers.Initialize(env); - members.Initialize(env); - - // 3. Register native functions. - RegisterNatives(env); - - // 4. Create JNI JVM. - JVM = JniJvm(jvm, javaMembers, members); - - char* printStack = getenv("IGNITE_CPP_PRINT_STACK"); - PRINT_EXCEPTION = printStack && strcmp("true", printStack) == 0; - } - else - { - GetJniErrorMessage(errMsg, res); - - errMsgLen = static_cast(errMsg.length()); - } - } - - if (JVM.GetJvm()) - ctx = new JniContext(&JVM, hnds); - } - catch (const JvmException&) - { - char* errClsNameChars = NULL; - char* errMsgChars = NULL; - char* stackTraceChars = NULL; - - // Read error info if possible. - javaMembers.WriteErrorInfo(env, &errClsNameChars, &errClsNameLen, &errMsgChars, &errMsgLen, - &stackTraceChars, &stackTraceLen); - - if (errClsNameChars) { - errClsName = errClsNameChars; - - delete[] errClsNameChars; - } - - if (errMsgChars) - { - errMsg = errMsgChars; - - delete[] errMsgChars; - } - - if (stackTraceChars) - { - stackTrace = stackTraceChars; - - delete[] stackTraceChars; - } - - // Destroy mmebers. - if (env) { - members.Destroy(env); - javaMembers.Destroy(env); - } - - // Destroy faulty JVM. - if (jvm) - jvm->DestroyJavaVM(); - } - - // It safe to release the lock at this point. - JVM_LOCK.Leave(); - - // Notify err callback if needed. - if (!ctx) { - if (errInfo) { - JniErrorInfo errInfo0(IGNITE_JNI_ERR_JVM_INIT, errClsName.c_str(), errMsg.c_str()); - - *errInfo = errInfo0; - } - - if (hnds.error) - hnds.error(hnds.target, IGNITE_JNI_ERR_JVM_INIT, errClsName.c_str(), errClsNameLen, - errMsg.c_str(), errMsgLen, stackTrace.c_str(), stackTraceLen, NULL, 0); - } - - return ctx; - } - - int JniContext::Reallocate(int64_t memPtr, int cap) { - JavaVM* jvm = JVM.GetJvm(); - - JNIEnv* env; - - int attachRes = jvm->AttachCurrentThread(reinterpret_cast(&env), NULL); - - if (attachRes == JNI_OK) - AttachHelper::OnThreadAttach(); - else - return -1; - - env->CallStaticVoidMethod(JVM.GetMembers().c_PlatformUtils, JVM.GetMembers().m_PlatformUtils_reallocate, memPtr, cap); - - if (env->ExceptionCheck()) { - env->ExceptionClear(); - - return -1; - } - - return 0; - } - - void JniContext::Detach() { - iocc::Memory::Fence(); - - if (JVM.GetJvm()) { - JNIEnv* env; - - JVM.GetJvm()->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); - - if (env) - JVM.GetJvm()->DetachCurrentThread(); - } - } - - jobject JniContext::DocumentDbConnect(const char* connectionString, - JniErrorInfo* errInfo) { - JNIEnv* env = Attach(); - jstring jConnectionString = - env->NewStringUTF(connectionString); - jobject connection = env->CallStaticObjectMethod( - jvm->GetMembers().c_DriverManager, - jvm->GetMembers().m_DriverManagerGetConnection, jConnectionString); - ExceptionCheck(env, errInfo); - return connection; - } - - void JniContext::DocumentDbDisconnect(const jobject connection, JniErrorInfo* errInfo) { - if (!connection) { - return; - } - JNIEnv* env = Attach(); - env->CallVoidMethod(connection, jvm->GetMembers().m_JavaSqlConnectionClose); - ExceptionCheck(env, errInfo); - env->DeleteLocalRef(connection); - } - - int64_t JniContext::TargetInLongOutLong(jobject obj, int opType, int64_t val, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - int64_t res = env->CallLongMethod(obj, jvm->GetMembers().m_PlatformTarget_inLongOutLong, opType, val); - - ExceptionCheck(env, err); - - return res; - } - - int64_t JniContext::TargetInStreamOutLong(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - int64_t res = env->CallLongMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutLong, opType, memPtr); - - ExceptionCheck(env, err); - - return res; - } - - void JniContext::TargetInStreamOutStream(jobject obj, int opType, int64_t inMemPtr, int64_t outMemPtr, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutStream, opType, inMemPtr, outMemPtr); - - ExceptionCheck(env, err); - } - - jobject JniContext::TargetInStreamOutObject(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObject, opType, memPtr); - - ExceptionCheck(env, err); - - return LocalToGlobal(env, res); - } - - jobject JniContext::TargetInObjectStreamOutObjectStream(jobject obj, int opType, void* arg, int64_t inMemPtr, int64_t outMemPtr, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_inObjectStreamOutObjectStream, opType, arg, inMemPtr, outMemPtr); - - ExceptionCheck(env, err); - - return LocalToGlobal(env, res); - } - - void JniContext::TargetOutStream(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformTarget_outStream, opType, memPtr); - - ExceptionCheck(env, err); - } - - jobject JniContext::TargetOutObject(jobject obj, int opType, JniErrorInfo* err) - { - JNIEnv* env = Attach(); - - jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_outObject, opType); - - ExceptionCheck(env, err); - - return LocalToGlobal(env, res); - } - - void JniContext::TargetInStreamAsync(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamAsync, opType, memPtr); - - ExceptionCheck(env, err); - } - - jobject JniContext::TargetInStreamOutObjectAsync(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObjectAsync, opType, memPtr); - - ExceptionCheck(env, err); - - return LocalToGlobal(env, res); - } - - jobject JniContext::CacheOutOpQueryCursor(jobject obj, int type, int64_t memPtr, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - jobject res = env->CallObjectMethod( - obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObject, type, memPtr); - - ExceptionCheck(env, err); - - return LocalToGlobal(env, res); - } - - jobject JniContext::CacheOutOpContinuousQuery(jobject obj, int type, int64_t memPtr, JniErrorInfo* err) { - JNIEnv* env = Attach(); - - jobject res = env->CallObjectMethod( - obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObject, type, memPtr); - - ExceptionCheck(env, err); - - return LocalToGlobal(env, res); - } - - jobject JniContext::Acquire(jobject obj) - { - if (obj) { - - JNIEnv* env = Attach(); - - jobject obj0 = env->NewGlobalRef(obj); - - ExceptionCheck(env); - - return obj0; - } - - return NULL; - } - - void JniContext::Release(jobject obj) { - if (obj) - { - JavaVM* jvm = JVM.GetJvm(); - - if (jvm) - { - JNIEnv* env; - - jint attachRes = jvm->AttachCurrentThread(reinterpret_cast(&env), NULL); - - if (attachRes == JNI_OK) - { - AttachHelper::OnThreadAttach(); - - env->DeleteGlobalRef(obj); - } - } - } - } - - void JniContext::SetConsoleHandler(ConsoleWriteHandler consoleHandler) { - if (!consoleHandler) - throw std::invalid_argument("consoleHandler can not be null"); - - CONSOLE_LOCK.Enter(); - - consoleWriteHandlers.push_back(consoleHandler); - - CONSOLE_LOCK.Leave(); - } - - int JniContext::RemoveConsoleHandler(ConsoleWriteHandler consoleHandler) { - if (!consoleHandler) - throw std::invalid_argument("consoleHandler can not be null"); - - CONSOLE_LOCK.Enter(); - - int oldSize = static_cast(consoleWriteHandlers.size()); - - consoleWriteHandlers.erase(remove(consoleWriteHandlers.begin(), consoleWriteHandlers.end(), - consoleHandler), consoleWriteHandlers.end()); - - int removedCnt = oldSize - static_cast(consoleWriteHandlers.size()); - - CONSOLE_LOCK.Leave(); - - return removedCnt; - } - - void JniContext::ThrowToJava(char* msg) { - JNIEnv* env = Attach(); - - env->ThrowNew(jvm->GetMembers().c_IgniteException, msg); - } - - void JniContext::DestroyJvm() { - jvm->GetJvm()->DestroyJavaVM(); - } - - /** - * Attach thread to JVM. - */ - JNIEnv* JniContext::Attach() { - JNIEnv* env; - - jint attachRes = jvm->GetJvm()->AttachCurrentThread(reinterpret_cast(&env), NULL); - - if (attachRes == JNI_OK) - AttachHelper::OnThreadAttach(); - else { - if (hnds.error) - hnds.error(hnds.target, IGNITE_JNI_ERR_JVM_ATTACH, NULL, 0, NULL, 0, NULL, 0, NULL, 0); - } - - return env; - } - - void JniContext::ExceptionCheck(JNIEnv* env) { - ExceptionCheck(env, NULL); - } - - void JniContext::ExceptionCheck(JNIEnv* env, JniErrorInfo* errInfo) - { - if (env->ExceptionCheck()) { - jthrowable err = env->ExceptionOccurred(); - - if (PRINT_EXCEPTION) - env->CallVoidMethod(err, jvm->GetJavaMembers().m_Throwable_printStackTrace); - - env->ExceptionClear(); - - // Get error class name and message. - jclass cls = env->GetObjectClass(err); - - jstring clsName = static_cast(env->CallObjectMethod(cls, jvm->GetJavaMembers().m_Class_getName)); - jstring msg = static_cast(env->CallObjectMethod(err, jvm->GetJavaMembers().m_Throwable_getMessage)); - int traceLen = 0; - std::string trace0 = ""; - if (jvm->GetJavaMembers().c_PlatformUtils - && jvm->GetJavaMembers() - .m_PlatformUtils_getFullStackTrace) { - jstring trace = static_cast< jstring >( - env->CallStaticObjectMethod( - jvm->GetJavaMembers().c_PlatformUtils, - jvm->GetJavaMembers() - .m_PlatformUtils_getFullStackTrace, - err)); - - trace0 = - JavaStringToCString(env, trace, &traceLen); - } - - env->DeleteLocalRef(cls); - - int clsNameLen; - std::string clsName0 = JavaStringToCString(env, clsName, &clsNameLen); - - int msgLen; - std::string msg0 = JavaStringToCString(env, msg, &msgLen); - - if (errInfo) - { - JniErrorInfo errInfo0(IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), msg0.c_str()); - - *errInfo = errInfo0; - } - - // Get error additional data (if any). - jbyteArray errData = nullptr; - if (jvm->GetMembers().c_PlatformUtils - && jvm->GetMembers().m_PlatformUtils_errData) { - errData = static_cast< jbyteArray >( - env->CallStaticObjectMethod( - jvm->GetMembers().c_PlatformUtils, - jvm->GetMembers().m_PlatformUtils_errData, - err)); - } - - if (errData) - { - jbyte* errBytesNative = env->GetByteArrayElements(errData, NULL); - - int errBytesLen = env->GetArrayLength(errData); - - if (hnds.error) - hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(), - msgLen, trace0.c_str(), traceLen, errBytesNative, errBytesLen); - - env->ReleaseByteArrayElements(errData, errBytesNative, JNI_ABORT); - } - else - { - if (hnds.error) - hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(), - msgLen, trace0.c_str(), traceLen, NULL, 0); - } - - env->DeleteLocalRef(err); - } - } - - /** - * Convert local reference to global. - */ - jobject JniContext::LocalToGlobal(JNIEnv* env, jobject localRef) { - if (localRef) { - jobject globalRef = env->NewGlobalRef(localRef); - - env->DeleteLocalRef(localRef); // Clear local ref irrespective of result. - - if (!globalRef) - ExceptionCheck(env); - - return globalRef; - } - else - return NULL; - } - - JNIEXPORT void JNICALL JniConsoleWrite(JNIEnv *env, jclass, jstring str, jboolean isErr) { - CONSOLE_LOCK.Enter(); - - if (consoleWriteHandlers.size() > 0) { - ConsoleWriteHandler consoleWrite = consoleWriteHandlers.at(0); - - const char* strChars = env->GetStringUTFChars(str, 0); - const int strCharsLen = env->GetStringUTFLength(str); - - consoleWrite(strChars, strCharsLen, isErr); - - env->ReleaseStringUTFChars(str, strChars); - } - - CONSOLE_LOCK.Leave(); - } - - JNIEXPORT void JNICALL JniLoggerLog(JNIEnv *env, jclass, jlong envPtr, jint level, jstring message, jstring category, jstring errorInfo, jlong memPtr) { - int messageLen; - char* messageChars = StringToChars(env, message, &messageLen); - - int categoryLen; - char* categoryChars = StringToChars(env, category, &categoryLen); - - int errorInfoLen; - char* errorInfoChars = StringToChars(env, errorInfo, &errorInfoLen); - - IGNITE_SAFE_PROC(env, envPtr, LoggerLogHandler, loggerLog, level, messageChars, messageLen, categoryChars, categoryLen, errorInfoChars, errorInfoLen, memPtr); - - if (messageChars) - delete[] messageChars; - - if (categoryChars) - delete[] categoryChars; - - if (errorInfoChars) - delete[] errorInfoChars; - } - - JNIEXPORT jboolean JNICALL JniLoggerIsLevelEnabled(JNIEnv *env, jclass, jlong envPtr, jint level) { - IGNITE_SAFE_FUNC(env, envPtr, LoggerIsLevelEnabledHandler, loggerIsLevelEnabled, level); - } - - JNIEXPORT jlong JNICALL JniInLongOutLong(JNIEnv *env, jclass, jlong envPtr, jint type, jlong val) { - IGNITE_SAFE_FUNC(env, envPtr, InLongOutLongHandler, inLongOutLong, type, val); - } - - JNIEXPORT jlong JNICALL JniInLongLongLongObjectOutLong(JNIEnv *env, jclass, jlong envPtr, jint type, jlong val1, jlong val2, jlong val3, jobject arg) { - IGNITE_SAFE_FUNC(env, envPtr, InLongLongLongObjectOutLongHandler, inLongLongLongObjectOutLong, type, val1, val2, val3, arg); - } - } // namespace java - } // namespace jni - } // namespace odbc -} // namespace ignite diff --git a/src/odbc/src/jni/os/linux/utils.cpp b/src/odbc/src/jni/os/linux/utils.cpp deleted file mode 100644 index 6fd4d6e7a..000000000 --- a/src/odbc/src/jni/os/linux/utils.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include - -#include - -#include -#include -#include -#include -#include - -#include "ignite/common/utils.h" -#include "ignite/common/fixed_size_array.h" - -#include "ignite/odbc/jni/utils.h" -#include "ignite/odbc/jni/java.h" - -using namespace ignite::common; -using namespace ignite::odbc::jni::java; - -namespace ignite -{ - namespace odbc { - namespace jni { - const char* JAVA_HOME = "JAVA_HOME"; - const char* JAVA_DLL1 = "/jre/lib/amd64/server/libjvm.so"; - const char* JAVA_DLL2 = "/lib/server/libjvm.so"; - const char* JAVA_DLL_DARWIN = "libjvm.dylib"; - - const char* DOCUMENTDB_HOME = "DOCUMENTDB_HOME"; - - const char* IGNITE_NATIVE_TEST_CLASSPATH = "IGNITE_NATIVE_TEST_CLASSPATH"; - - /** Excluded modules from test classpath. */ - const char* TEST_EXCLUDED_MODULES[] = {"rest-http"}; - - /** Key indicating that the thread is attached. */ - static pthread_key_t attachKey; - - /** Helper to ensure that attach key is allocated only once. */ - static pthread_once_t attachKeyInit = PTHREAD_ONCE_INIT; - - void DestroyAttachKey(void* key) { - delete reinterpret_cast< AttachHelper* >(key); - } - - void AllocateAttachKey() { - pthread_key_create(&attachKey, DestroyAttachKey); - } - - AttachHelper::~AttachHelper() { - JniContext::Detach(); - } - - void AttachHelper::OnThreadAttach() { - pthread_once(&attachKeyInit, AllocateAttachKey); - - void* val = pthread_getspecific(attachKey); - - if (!val) - pthread_setspecific(attachKey, new AttachHelper()); - } - - /** - * Checks if the path looks like binary release home directory. - * Internally checks for presence of some directories, that are - * @return @c true if the path looks like binary release home directory. - */ - bool LooksLikeBinaryReleaseHome(const std::string& path) { - static const char* PROBE_CORE_LIB = "/libs/ignite-core*.jar"; - - std::string coreLibProbe = path + PROBE_CORE_LIB; - - return FileExists(coreLibProbe); - } - - /** - * Checks if the path looks like source release home directory. - * Internally checks for presence of core source directory. - * @return @c true if the path looks like binary release home directory. - */ - bool LooksLikeSourceReleaseHome(const std::string& path) { - static const char* PROBE_CORE_SOURCE = - "/modules/core/src/main/java/org/apache/ignite"; - - std::string coreSourcePath = path + PROBE_CORE_SOURCE; - - return IsValidDirectory(coreSourcePath); - } - - /** - * Helper function for Ignite home resolution. - * Goes upwards in directory hierarchy and checks whether certain - * folders exist in the path. - * - * @param path Path to evaluate. - * @return res Resolved directory. Empty string if not found. - */ - std::string ResolveIgniteHome0(const std::string& path) { - if (!IsValidDirectory(path)) - return std::string(); - - // Remove trailing slashes, otherwise we will have an infinite loop. - size_t last = path.find_last_not_of("/ "); - - if (last == std::string::npos) - return std::string(); - - std::string path0(path, 0, last + 1); - - if (LooksLikeBinaryReleaseHome(path0) || LooksLikeSourceReleaseHome(path0)) - return path0; - - // Evaluate parent directory. - size_t slashPos = path0.find_last_of("/"); - - if (slashPos == std::string::npos) - return std::string(); - - std::string parent(path0, 0, slashPos); - - return ResolveIgniteHome0(parent); - } - - /** - * Create classpath picking JARs from the given path. - * - * @path Path. - * @return Classpath; - */ - std::string ClasspathJars(const std::string& path) { - std::string res; - - DIR* dir = opendir(path.c_str()); - - if (dir) { - struct dirent* entry; - - while ((entry = readdir(dir)) != NULL) { - char* dot = strrchr(entry->d_name, '.'); - if (dot && !strcmp(dot, ".jar")) { - res.append(path); - res.append("/"); - res.append(entry->d_name); - res.append(":"); - } - } - - closedir(dir); - } - - return res; - } - - /** - * Check if path corresponds to excluded module. - * - * @path Path. - * @return True if path should be excluded. - */ - bool IsExcludedModule(const std::string& path) { - std::string lower_path = path; - std::transform(path.begin(), path.end(), lower_path.begin(), ::tolower); - - for (size_t i = 0; i < sizeof(TEST_EXCLUDED_MODULES) / sizeof(char*); i++) { - if (lower_path.find(TEST_EXCLUDED_MODULES[i]) != std::string::npos) - return true; - } - - return false; - } - - /** - * Create classpath picking compiled classes from the given path. - * - * @path Path. - * @return Classpath; - */ - std::string ClasspathExploded(const std::string& path, bool down) { - std::string res; - - if (FileExists(path) && !IsExcludedModule(path)) { - // 1. Append "target\classes". - std::string classesPath = path + "/target/classes"; - - if (FileExists(classesPath)) { - res += classesPath; - res += ":"; - } - - // 2. Append "target\test-classes" - std::string testClassesPath = path + "/target/test-classes"; - - if (FileExists(testClassesPath)) { - res += testClassesPath; - res += ":"; - } - - // 3. Append "target\libs" - std::string libsPath = path + "/target/libs"; - - if (FileExists(libsPath)) { - std::string libsCp = ClasspathJars(libsPath); - res += libsCp; - } - - // 4. Do the same for child if needed. - if (down) { - DIR* dir = opendir(path.c_str()); - - if (dir) { - struct dirent* entry; - - while ((entry = readdir(dir)) != NULL) { - std::string entryPath = entry->d_name; - - if (entryPath.compare(".") != 0 - && entryPath.compare("..") != 0) { - std::string entryFullPath = path + "/" + entryPath; - - struct stat entryFullStat; - - if (stat(entryFullPath.c_str(), &entryFullStat) != -1 - && S_ISDIR(entryFullStat.st_mode)) { - std::string childCp = - ClasspathExploded(entryFullPath, false); - - res += childCp; - } - } - } - - closedir(dir); - } - } - } - - return res; - } - - std::string CreateDocumentDbHomeClasspath(const std::string& home, bool forceTest) { - std::string res = std::string(); - - // 1. Add exploded test directories. - if (forceTest) { - std::string examplesPath = home + "/examples"; - std::string examplesCp = ClasspathExploded(examplesPath, true); - res.append(examplesCp); - - std::string modulesPath = home + "/modules"; - std::string modulesCp = ClasspathExploded(modulesPath, true); - res.append(modulesCp); - } - - // 2. Add regular jars from "libs" folder excluding "optional". - std::string libsPath = home + "/libs"; - - if (FileExists(libsPath)) { - res.append(ClasspathJars(libsPath)); - - // Append inner directories. - DIR* dir = opendir(libsPath.c_str()); - - if (dir) { - struct dirent* entry; - - while ((entry = readdir(dir)) != NULL) { - std::string entryPath = entry->d_name; - - if (entryPath.compare(".") != 0 && entryPath.compare("..") != 0 - && entryPath.compare("optional") != 0) { - std::string entryFullPath = libsPath; - - entryFullPath.append("/"); - entryFullPath.append(entryPath); - - struct stat entryFullStat; - - if (stat(entryFullPath.c_str(), &entryFullStat) != -1 - && S_ISDIR(entryFullStat.st_mode)) - res.append(ClasspathJars(entryFullPath)); - } - } - - closedir(dir); - } - } - - // 3. Return. - return res; - } - - std::string FindJvmLibrary(const std::string& path) { - #ifdef __APPLE__ - return JAVA_DLL_DARWIN; - #else - // If path is provided explicitly, then check only it. - if (!path.empty() && FileExists(path)) - return path; - - std::string javaEnv = GetEnv(JAVA_HOME); - - if (!javaEnv.empty()) { - std::string javaDll = javaEnv + JAVA_DLL1; - - if (FileExists(javaDll)) - return javaDll; - - javaDll = javaEnv + JAVA_DLL2; - - if (FileExists(javaDll)) - return javaDll; - } - - return std::string(); - #endif - } - - bool LoadJvmLibrary(const std::string& path) { - #ifdef __APPLE__ - return RTLD_DEFAULT; - #else - void* hnd = dlopen(path.c_str(), RTLD_LAZY); - - return hnd != NULL; - #endif - } - - /** - * Create Ignite classpath based on user input and home directory. - * - * @param usrCp User's classpath. - * @param home Ignite home directory. - * @param forceTest Whether test classpath must be used. - * @return Classpath. - */ - std::string CreateIgniteClasspath(const std::string& usrCp, - const std::string* home, bool forceTest) { - // 1. Append user classpath if it exists. - std::string cp; - - if (!usrCp.empty()) { - cp.append(usrCp); - - if (*cp.rbegin() != ';') - cp.push_back(';'); - } - - // 2. Append home classpath if home is defined. - if (home) { - std::string homeCp = CreateDocumentDbHomeClasspath(*home, forceTest); - - cp.append(homeCp); - } - - // 3. Return. - return cp; - } - - /** - * Adds semicolon at the end of the path if needed. - * @param usrCp Classpath provided by user. - * @return Normalized classpath. - */ - std::string NormalizeClasspath(const std::string& usrCp) { - if (usrCp.empty() || *usrCp.rbegin() == ';') - return usrCp; - - return usrCp + ';'; - } - - std::string CreateDocumentDbClasspath(const std::string& usrCp, - const std::string& home) { - // 1. Append user classpath if it exists. - std::string cp = NormalizeClasspath(usrCp); - - // 2. Append home classpath - if (!home.empty()) { - std::string env = GetEnv(IGNITE_NATIVE_TEST_CLASSPATH, "false"); - - bool forceTest = ToLower(env) == "true"; - - std::string homeCp = CreateDocumentDbHomeClasspath(home, forceTest); - - cp.append(homeCp); - } - - // 3. Return. - return cp; - } - - std::string ResolveDocumentDbHome(const std::string& path) { - // 1. Check passed argument. - if (IsValidDirectory(path)) - return path; - - // 2. Check environment variable. - std::string home = GetEnv(DOCUMENTDB_HOME); - - if (IsValidDirectory(home)) - return home; - - // 3. Check current work dir. - FixedSizeArray< char > curDir(1024 * 16); - - char* res = getcwd(curDir.GetData(), curDir.GetSize()); - - if (!res) - return std::string(); - - std::string curDirStr(curDir.GetData()); - - return ResolveIgniteHome0(curDirStr); - } - } // namespace jni - } // namespace odbc -} diff --git a/src/odbc/src/jni/os/win/utils.cpp b/src/odbc/src/jni/os/win/utils.cpp deleted file mode 100644 index e41fb56af..000000000 --- a/src/odbc/src/jni/os/win/utils.cpp +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "ignite/common/concurrent.h" -#include "ignite/common/utils.h" -#include "ignite/common/fixed_size_array.h" - -#include "ignite/odbc/jni/utils.h" -#include "ignite/odbc/jni/java.h" - -using namespace ignite::common; -using namespace ignite::common::concurrent; - -using namespace ignite::odbc::jni::java; - -namespace ignite -{ - namespace odbc - { - namespace jni - { - const char* JAVA_HOME = "JAVA_HOME"; - const char* JAVA_DLL1 = "\\jre\\bin\\server\\jvm.dll"; - const char* JAVA_DLL2 = "\\bin\\server\\jvm.dll"; - - const char* DOCUMENTDB_HOME = "DOCUMENTDB_HOME"; - - const char* IGNITE_NATIVE_TEST_CLASSPATH = "IGNITE_NATIVE_TEST_CLASSPATH"; - - /** Excluded modules from test classpath. */ - const char* TEST_EXCLUDED_MODULES[] = { "rest-http" }; - - AttachHelper::~AttachHelper() - { - // No-op. - } - - void AttachHelper::OnThreadAttach() - { - // No-op. - } - - /** - * Checks if the path looks like binary release home directory. - * Internally checks for presence of core library. - * @return @c true if the path looks like binary release home directory. - */ - bool LooksLikeBinaryReleaseHome(const std::string& path) - { - static const char* PROBE_CORE_LIB = "\\libs\\ignite-core*.jar"; - - std::string coreLibProbe = path + PROBE_CORE_LIB; - - return FileExists(coreLibProbe); - } - - /** - * Checks if the path looks like source release home directory. - * Internally checks for presence of core source directory. - * @return @c true if the path looks like binary release home directory. - */ - bool LooksLikeSourceReleaseHome(const std::string& path) - { - static const char* PROBE_CORE_SOURCE = "\\modules\\core\\src\\main\\java\\org\\apache\\ignite"; - - std::string coreSourcePath = path + PROBE_CORE_SOURCE; - - return IsValidDirectory(coreSourcePath); - } - - /** - * Helper function for Ignite home resolution. - * Goes upwards in directory hierarchy and checks whether certain - * folders exist in the path. - * - * @param path Path to evaluate. - * @return res Resolved directory. Empty string if not found. - */ - std::string ResolveIgniteHome0(const std::string& path) - { - if (!IsValidDirectory(path)) - return std::string(); - - // Remove trailing slashes, otherwise we will have an infinite loop. - size_t last = path.find_last_not_of("/\\ "); - - if (last == std::string::npos) - return std::string(); - - std::string path0(path, 0, last + 1); - - if (LooksLikeBinaryReleaseHome(path0) || LooksLikeSourceReleaseHome(path0)) - return path0; - - // Evaluate parent directory. - size_t slashPos = path0.find_last_of("/\\"); - - if (slashPos == std::string::npos) - return std::string(); - - std::string parent(path0, 0, slashPos); - - return ResolveIgniteHome0(parent); - } - - /** - * Create classpath picking JARs from the given path. - * - * @path Path. - * @return Classpath; - */ - std::string ClasspathJars(const std::string& path) - { - std::string searchPath = path + "\\*.jar"; - - WIN32_FIND_DATAA findData; - - HANDLE hnd = FindFirstFileA(searchPath.c_str(), &findData); - - if (hnd == INVALID_HANDLE_VALUE) - return std::string(); - - std::string res; - - do - { - res.append(path); - res.append("\\"); - res.append(findData.cFileName); - res.append(";"); - } while (FindNextFileA(hnd, &findData) != 0); - - FindClose(hnd); - - return res; - } - - /** - * Check if path corresponds to excluded module. - * - * @path Path. - * @return True if path should be excluded. - */ - bool IsExcludedModule(const std::string& path) { - std::string lower_path = path; - std::transform(path.begin(), path.end(), lower_path.begin(), ::tolower); - - for (size_t i = 0; i < sizeof(TEST_EXCLUDED_MODULES) / sizeof(char*); i++) { - if (lower_path.find(TEST_EXCLUDED_MODULES[i]) != std::string::npos) - return true; - } - - return false; - } - - /** - * Create classpath picking compiled classes from the given path. - * - * @path Path. - * @return Classpath; - */ - std::string ClasspathExploded(const std::string& path, bool down) - { - std::string res; - - if (FileExists(path) && !IsExcludedModule(path)) - { - // 1. Append "target\classes". - std::string classesPath = path + "\\target\\classes"; - - if (FileExists(classesPath)) { - res.append(classesPath); - res.append(";"); - } - - // 2. Append "target\test-classes" - std::string testClassesPath = path + "\\target\\test-classes"; - - if (FileExists(testClassesPath)) { - res.append(testClassesPath); - res.append(";"); - } - - // 3. Append "target\libs" - std::string libsPath = path + "\\target\\libs"; - - if (FileExists(libsPath)) { - std::string libsCp = ClasspathJars(libsPath); - res.append(libsCp); - } - - // 4. Do the same for child if needed. - if (down) - { - std::string searchPath = path + "\\*"; - - WIN32_FIND_DATAA findData; - - HANDLE hnd = FindFirstFileA(searchPath.c_str(), &findData); - - if (hnd != INVALID_HANDLE_VALUE) - { - do - { - if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - std::string childPath = findData.cFileName; - - if (childPath.compare(".") != 0 && - childPath.compare("..") != 0) - { - std::string childCp = - ClasspathExploded(path + "\\" + childPath, false); - - res.append(childCp); - } - } - } while (FindNextFileA(hnd, &findData) != 0); - - FindClose(hnd); - } - } - } - - return res; - } - - std::string CreateDocumentDbHomeClasspath(const std::string& home, bool forceTest) - { - std::string res; - - // 1. Add exploded test directories. - if (forceTest) - { - std::string examplesPath = home + "\\examples"; - std::string examplesCp = ClasspathExploded(examplesPath, true); - res.append(examplesCp); - - std::string modulesPath = home + "\\modules"; - std::string modulesCp = ClasspathExploded(modulesPath, true); - res.append(modulesCp); - } - - // 2. Add regular jars from "libs" folder excluding "optional". - std::string libsPath = home + "\\libs"; - - if (FileExists(libsPath)) - { - res.append(ClasspathJars(libsPath)); - - // Append inner directories. - std::string libsSearchPath = libsPath + "\\*"; - - WIN32_FIND_DATAA libsFindData; - - HANDLE libsHnd = FindFirstFileA(libsSearchPath.c_str(), &libsFindData); - - if (libsHnd != INVALID_HANDLE_VALUE) - { - do - { - if (libsFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - { - std::string libsChildPath = libsFindData.cFileName; - - if (libsChildPath.compare(".") != 0 && - libsChildPath.compare("..") != 0 && - libsChildPath.compare("optional") != 0) { - std::string libsFolder = libsPath + "\\" + libsChildPath; - - res.append(ClasspathJars(libsFolder)); - } - } - } while (FindNextFileA(libsHnd, &libsFindData) != 0); - - FindClose(libsHnd); - } - } - - // 3. Return. - return res; - } - - std::string FindJvmLibrary(const std::string& path) - { - // If path is provided explicitly, then check only it. - if (!path.empty() && FileExists(path)) - return path; - - std::string javaEnv = GetEnv(JAVA_HOME); - - if (!javaEnv.empty()) - { - std::string javaDll = javaEnv + JAVA_DLL1; - - if (FileExists(javaDll)) - return javaDll; - - javaDll = javaEnv + JAVA_DLL2; - - if (FileExists(javaDll)) - return javaDll; - } - - return std::string(); - } - - bool LoadJvmLibrary(const std::string& path) - { - HMODULE mod = LoadLibraryA(path.c_str()); - - return mod != NULL; - } - - /** - * Create Ignite classpath based on user input and home directory. - * - * @param usrCp User's classpath. - * @param home Ignite home directory. - * @param forceTest Whether test classpath must be used. - * @return Classpath. - */ - std::string CreateIgniteClasspath(const std::string& usrCp, const std::string* home, bool forceTest) - { - // 1. Append user classpath if it exists. - std::string cp; - - if (!usrCp.empty()) - { - cp.append(usrCp); - - if (*cp.rbegin() != ';') - cp.push_back(';'); - } - - // 2. Append home classpath if home is defined. - if (home) - { - std::string homeCp = CreateDocumentDbHomeClasspath(*home, forceTest); - - cp.append(homeCp); - } - - // 3. Return. - return cp; - } - - /** - * Adds semicolon at the end of the path if needed. - * @param usrCp Classpath provided by user. - * @return Normalized classpath. - */ - std::string NormalizeClasspath(const std::string& usrCp) - { - if (usrCp.empty() || *usrCp.rbegin() == ';') - return usrCp; - - return usrCp + ';'; - } - - std::string CreateDocumentDbClasspath(const std::string& usrCp, const std::string& home) - { - // 1. Append user classpath if it exists. - std::string cp = NormalizeClasspath(usrCp); - - // 2. Append home classpath - if (!home.empty()) - { - std::string env = GetEnv(IGNITE_NATIVE_TEST_CLASSPATH, "false"); - - bool forceTest = ToLower(env) == "true"; - - std::string homeCp = CreateDocumentDbHomeClasspath(home, forceTest); - - cp.append(homeCp); - } - - // 3. Return. - return cp; - } - - std::string ResolveDocumentDbHome(const std::string& path) - { - // 1. Check passed argument. - if (IsValidDirectory(path)) - return path; - - // 2. Check environment variable. - std::string home = GetEnv(DOCUMENTDB_HOME); - - if (IsValidDirectory(home)) - return home; - - // 3. Check current work dir. - DWORD curDirLen = GetCurrentDirectoryA(0, NULL); - - if (!curDirLen) - return std::string(); - - FixedSizeArray curDir(curDirLen); - - curDirLen = GetCurrentDirectoryA(curDir.GetSize(), curDir.GetData()); - - if (!curDirLen) - return std::string(); - - std::string curDirStr(curDir.GetData()); - - return ResolveIgniteHome0(curDirStr); - } - } // jni - } // odbc -} // ignite - -BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved) -{ - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - if (!ThreadLocal::OnProcessAttach()) - return FALSE; - - break; - - case DLL_THREAD_DETACH: - ThreadLocal::OnThreadDetach(); - - JniContext::Detach(); - - break; - - case DLL_PROCESS_DETACH: - ThreadLocal::OnProcessDetach(); - - break; - - default: - break; - } - - return TRUE; -} \ No newline at end of file diff --git a/src/odbc/src/log.cpp b/src/odbc/src/log.cpp index 80f0b8b88..755798f48 100644 --- a/src/odbc/src/log.cpp +++ b/src/odbc/src/log.cpp @@ -67,7 +67,7 @@ namespace ignite { if (IsEnabled()) { - common::concurrent::CsLockGuard guard(mutex); + ignite::common::concurrent::CsLockGuard guard(mutex); stream << message << std::endl; } } diff --git a/src/odbc/src/protocol_version.cpp b/src/odbc/src/protocol_version.cpp index f196b33e7..a073ab26c 100644 --- a/src/odbc/src/protocol_version.cpp +++ b/src/odbc/src/protocol_version.cpp @@ -17,7 +17,7 @@ #include -#include +#include #include "ignite/odbc/protocol_version.h" #include "ignite/odbc/utility.h" diff --git a/src/odbc/src/ssl_mode.cpp b/src/odbc/src/ssl_mode.cpp index 0f5aba861..70fd05891 100644 --- a/src/odbc/src/ssl_mode.cpp +++ b/src/odbc/src/ssl_mode.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include "ignite/odbc/ssl_mode.h" diff --git a/src/odbc/src/utility.cpp b/src/odbc/src/utility.cpp index 8ac9221f7..c060a0ada 100644 --- a/src/odbc/src/utility.cpp +++ b/src/odbc/src/utility.cpp @@ -67,7 +67,7 @@ namespace ignite writer.WriteString(str.data(), static_cast(str.size())); } - void ReadDecimal(ignite::impl::binary::BinaryReaderImpl& reader, odbc::common::Decimal& decimal) + void ReadDecimal(ignite::impl::binary::BinaryReaderImpl& reader, common::Decimal& decimal) { int8_t hdr = reader.ReadInt8(); @@ -94,20 +94,20 @@ namespace ignite sign = -1; } - odbc::common::Decimal res(mag.data(), static_cast(mag.size()), scale, sign); + common::Decimal res(mag.data(), static_cast(mag.size()), scale, sign); decimal.Swap(res); } - void WriteDecimal(ignite::impl::binary::BinaryWriterImpl& writer, const odbc::common::Decimal& decimal) + void WriteDecimal(ignite::impl::binary::BinaryWriterImpl& writer, const common::Decimal& decimal) { writer.WriteInt8(ignite::impl::binary::IGNITE_TYPE_DECIMAL); - const odbc::common::BigInteger &unscaled = decimal.GetUnscaledValue(); + const common::BigInteger &unscaled = decimal.GetUnscaledValue(); writer.WriteInt32(decimal.GetScale()); - odbc::common::FixedSizeArray magnitude; + common::FixedSizeArray magnitude; unscaled.MagnitudeToBytes(magnitude); From 4d704df11a5d29eddce6e35e47f4572ff111d2ad Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 26 Jan 2022 12:00:20 -0800 Subject: [PATCH 086/165] [AD-522] keyboard user interface design + disable DSN empty strimg warning dialog * make cursor go to checkboxes on the Config window and not skip them when tab key is pressed * when DSN field is empty, Ok Button is disabled * make default replicaSet value empty string (default is disable repliaSet) * refactor - removed unneeded comments --- .../os/win/src/system/ui/custom_window.cpp | 4 +- .../system/ui/dsn_configuration_window.cpp | 69 ++++++------------- src/odbc/src/config/configuration.cpp | 2 +- 3 files changed, 24 insertions(+), 51 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/custom_window.cpp b/src/odbc/os/win/src/system/ui/custom_window.cpp index 57690a3a4..ebc569efa 100644 --- a/src/odbc/os/win/src/system/ui/custom_window.cpp +++ b/src/odbc/os/win/src/system/ui/custom_window.cpp @@ -162,7 +162,7 @@ namespace ignite { std::auto_ptr child(new Window(this, "Button", title)); - child->Create(WS_CHILD | WS_VISIBLE | BS_CHECKBOX, posX, posY, sizeX, sizeY, id); + child->Create(WS_CHILD | WS_VISIBLE | BS_CHECKBOX | WS_TABSTOP, posX, posY, sizeX, sizeY, id); child->SetChecked(state); @@ -174,7 +174,7 @@ namespace ignite { std::auto_ptr child(new Window(this, "Combobox", title)); - child->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, posX, posY, sizeX, sizeY, id); + child->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_TABSTOP, posX, posY, sizeX, sizeY, id); return child; } diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index b3a35c843..06b77c3b3 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -24,7 +24,6 @@ #include "ignite/odbc/system/ui/dsn_configuration_window.h" #include "ignite/odbc/config/config_tools.h" -#include "ignite/odbc/diagnostic/diagnosable_adapter.h" namespace ignite { @@ -36,10 +35,7 @@ namespace ignite { DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, config::Configuration& config): CustomWindow(parent, "IgniteConfigureDsn", "Configure Amazon DocumentDB DSN Latest"), - //width(360), // original width:360. - //height(600), // original height:600 - width(730), // double the original width - //width(360), + width(730), height(515), connectionSettingsGroupBox(), tlsSettingsGroupBox(), @@ -130,26 +126,17 @@ namespace ignite void DsnConfigurationWindow::OnCreate() { int groupPosYLeft = MARGIN; - //int groupSizeY = width - 2 * MARGIN; // original int groupSizeY = width / 2 - 2 * MARGIN; int posXRight = width / 2 + MARGIN; - //int posXRight = MARGIN + (width - MARGIN) / 2; - //int posXRight = MARGIN + groupSizeY; - //int posXRight = 2 * MARGIN + groupSizeY; int groupPosYRight = MARGIN; // create left column group settings groupPosYLeft += INTERVAL + CreateConnectionSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); - //groupPosYLeft += INTERVAL + CreateAuthSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); groupPosYLeft += INTERVAL + CreateTlsSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); groupPosYLeft += INTERVAL + CreateSchemaSettingsGroup(MARGIN, groupPosYLeft, groupSizeY); // create right column group settings groupPosYRight += INTERVAL + CreateSshSettingsGroup(posXRight, groupPosYRight, groupSizeY); groupPosYRight += INTERVAL + CreateAdditionalSettingsGroup(posXRight, groupPosYRight, groupSizeY); - //groupPosY += INTERVAL + CreateSslSettingsGroup(MARGIN, groupPosY, groupSizeY); - //groupPosY += INTERVAL + CreateAdditionalSettingsGroup(MARGIN, groupPosY, groupSizeY); - // test: if above code is commented out, additional settings shouldn't appear in config window. Result: Yes test success. - // what happens here is the height of each subgroup is calculated and appended to the y position of the buttons int cancelPosX = width - MARGIN - BUTTON_WIDTH; int okPosX = cancelPosX - INTERVAL - BUTTON_WIDTH; @@ -161,14 +148,9 @@ namespace ignite // check whether the required fields are filled. If not, Ok button is disabled. created = true; okButton->SetEnabled( - userEdit->HasText() && passwordEdit->HasText() - && databaseEdit->HasText() && hostnameEdit->HasText() - && portEdit->HasText()); - - // original code by Ignite - //okButton = CreateButton(okPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, "Ok", ChildId::OK_BUTTON); - //cancelButton = CreateButton(cancelPosX, groupPosY, BUTTON_WIDTH, BUTTON_HEIGHT, - // "Cancel", ChildId::CANCEL_BUTTON); + nameEdit->HasText() && userEdit->HasText() + && passwordEdit->HasText() && databaseEdit->HasText() + && hostnameEdit->HasText() && portEdit->HasText()); } int DsnConfigurationWindow::CreateConnectionSettingsGroup(int posX, int posY, int sizeX) @@ -184,14 +166,14 @@ namespace ignite const char* val = config.GetDsn().c_str(); nameLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Data Source Name:", ChildId::NAME_LABEL); + "Data Source Name*:", ChildId::NAME_LABEL); nameEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::NAME_EDIT); rowPos += INTERVAL + ROW_HEIGHT; val = config.GetHostname().c_str(); hostnameLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Hostname :", ChildId::HOST_NAME_LABEL); + "Hostname*:", ChildId::HOST_NAME_LABEL); hostnameEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::HOST_NAME_EDIT); @@ -201,7 +183,7 @@ namespace ignite val = tmp.c_str(); portLabel = CreateLabel( labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Port:", ChildId::PORT_LABEL); + "Port*:", ChildId::PORT_LABEL); portEdit = CreateEdit( editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::PORT_EDIT, ES_NUMBER); @@ -211,21 +193,21 @@ namespace ignite val = config.GetDatabase().c_str(); databaseLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Database :", ChildId::DATABASE_LABEL); + "Database*:", ChildId::DATABASE_LABEL); databaseEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::DATABASE_EDIT); rowPos += INTERVAL + ROW_HEIGHT; val = config.GetUser().c_str(); - userLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "User :", ChildId::USER_LABEL); + userLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "User* :", ChildId::USER_LABEL); userEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::USER_EDIT); rowPos += INTERVAL + ROW_HEIGHT; val = config.GetPassword().c_str(); passwordLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "Password:", ChildId::PASSWORD_LABEL); + "Password*:", ChildId::PASSWORD_LABEL); passwordEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::USER_EDIT, ES_PASSWORD); @@ -257,14 +239,14 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; const char* val = config.GetSshUser().c_str(); - sshUserLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSH User :", ChildId::SSH_USER_LABEL); + sshUserLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "SSH User:", ChildId::SSH_USER_LABEL); sshUserEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_USER_EDIT); rowPos += INTERVAL + ROW_HEIGHT; val = config.GetSshHost().c_str(); sshHostLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSH Hostname :", ChildId::SSH_HOST_LABEL); + "SSH Hostname:", ChildId::SSH_HOST_LABEL); sshHostEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_HOST_EDIT); @@ -272,7 +254,7 @@ namespace ignite val = config.GetSshPrivateKeyFile().c_str(); sshPrivateKeyFileLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, - "SSH Private Key File :", ChildId::SSH_PRIVATE_KEY_FILE_LABEL); + "SSH Private Key File:", ChildId::SSH_PRIVATE_KEY_FILE_LABEL); sshPrivateKeyFileEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_PRIVATE_KEY_FILE_EDIT); @@ -281,7 +263,7 @@ namespace ignite val = config.GetSshPrivateKeyPassphrase().c_str(); // ssh private key passphrase label requires double the row height due to the long label. sshPrivateKeyPassphraseLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT * 2, - "SSH Private Key Passphrase :", ChildId::SSH_PRIVATE_KEY_PASSPHRASE_LABEL); + "SSH Private Key Passphrase:", ChildId::SSH_PRIVATE_KEY_PASSPHRASE_LABEL); sshPrivateKeyPassphraseEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT * 2, val, ChildId::SSH_PRIVATE_KEY_PASSPHRASE_EDIT); @@ -561,6 +543,7 @@ namespace ignite break; } + case ChildId::NAME_EDIT: case ChildId::HOST_NAME_EDIT: case ChildId::PORT_EDIT: case ChildId::DATABASE_EDIT: @@ -570,11 +553,12 @@ namespace ignite // if window has been created. Check if (created) { okButton->SetEnabled( - userEdit->HasText() - && passwordEdit->HasText() - && databaseEdit->HasText() - && hostnameEdit->HasText() - && portEdit->HasText()); + nameEdit->HasText() + && userEdit->HasText() + && passwordEdit->HasText() + && databaseEdit->HasText() + && hostnameEdit->HasText() + && portEdit->HasText()); } break; } @@ -721,17 +705,6 @@ namespace ignite // username and password intentionally not logged for security reasons - if (dsnStr.empty()) - throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "DSN name can not be empty."); - - diagnostic::DiagnosticRecordStorage diag; - - if (diag.GetStatusRecordsNumber() > 0) - { - throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, - diag.GetStatusRecord(1).GetMessageText().c_str()); - } - cfg.SetDsn(dsnStr); cfg.SetTcpPort(port); cfg.SetHostname(hostnameStr); diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 1d025d4e6..0d120b27b 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -64,7 +64,7 @@ namespace ignite const std::string Configuration::DefaultValue::appName = "Amazon DocumentDB ODBC Driver"; const int32_t Configuration::DefaultValue::loginTimeoutSec = 0; const ReadPreference::Type Configuration::DefaultValue::readPreference = ReadPreference::Type::PRIMARY; - const std::string Configuration::DefaultValue::replicaSet = "rs0"; + const std::string Configuration::DefaultValue::replicaSet = ""; const bool Configuration::DefaultValue::retryReads = true; const int32_t Configuration::DefaultValue::defaultFetchSize = 2000; From 124142934f3c5ede9309ca691434c1bb16653376 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 26 Jan 2022 17:03:02 -0800 Subject: [PATCH 087/165] [AD-522] add end_point header to resolve build errors end_point related code still exist in connection.cpp, so I readded the header for end_point --- src/odbc/src/connection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index b347c5035..066ffab76 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -28,6 +28,7 @@ #include "ignite/odbc/log.h" #include "ignite/odbc/utility.h" #include "ignite/odbc/environment.h" +#include "ignite/odbc/end_point.h" #include "ignite/odbc/statement.h" #include "ignite/odbc/connection.h" #include "ignite/odbc/message.h" From c66e84d4264595e146d7fab7d3ec52942bd7f85a Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 27 Jan 2022 10:58:54 -0800 Subject: [PATCH 088/165] Revert "Revert "Merge branch 'develop' into alinaliBQ/AD-522/config_window"" This reverts commit df0cad5490612c695ca28cc8ee44c73dbb1b68bd. --- .github/workflows/checks.yml | 1 - .github/workflows/mac-build.yml | 26 +- .github/workflows/mac-debug-build.yml | 1 + .github/workflows/win-build.yml | 79 +- README.md | 10 +- build_mac_debug64.sh | 21 + build_mac_release64.sh | 26 +- scripts/build_windows.ps1 | 15 + scripts/register_driver_macos.sh | 27 + .../include/ignite/common/big_integer.h | 2 +- src/common/include/ignite/common/decimal.h | 6 +- src/odbc-test/CMakeLists.txt | 43 +- src/odbc-test/config/ssh_config | 2 + src/odbc-test/include/odbc_test_suite.h | 12 +- src/odbc-test/include/test_utils.h | 47 +- src/odbc-test/src/connection_test.cpp | 86 +- src/odbc-test/src/odbc_test_suite.cpp | 27 +- src/odbc-test/src/test_utils.cpp | 95 +- src/odbc/CMakeLists.txt | 35 +- .../ignite/odbc/app/application_data_buffer.h | 2 +- .../include/ignite/odbc/common/big_integer.h | 526 ++++++++ src/odbc/include/ignite/odbc/common/bits.h | 221 ++++ .../include/ignite/odbc/common/concurrent.h | 605 +++++++++ src/odbc/include/ignite/odbc/common/decimal.h | 530 ++++++++ .../ignite/odbc/common/default_allocator.h | 92 ++ .../ignite/odbc/common/dynamic_size_array.h | 418 +++++++ .../include/ignite/odbc/common/expected.h | 303 +++++ .../ignite/odbc/common/fixed_size_array.h | 262 ++++ .../ignite/odbc/common/platform_utils.h | 126 ++ src/odbc/include/ignite/odbc/common/utils.h | 664 ++++++++++ src/odbc/include/ignite/odbc/connection.h | 31 +- src/odbc/include/ignite/odbc/ignite_error.h | 316 +++++ src/odbc/include/ignite/odbc/jni/java.h | 641 ++++++++++ src/odbc/include/ignite/odbc/jni/utils.h | 193 +++ src/odbc/include/ignite/odbc/log.h | 6 +- .../include/ignite/odbc/meta/column_meta.h | 2 +- .../ignite/odbc/meta/primary_key_meta.h | 2 +- src/odbc/include/ignite/odbc/odbc_error.h | 6 +- src/odbc/include/ignite/odbc/utility.h | 8 +- src/odbc/install/install_amd64.cmd | 3 +- .../linux/include/ignite/odbc/common/common.h | 56 + .../ignite/odbc/common/concurrent_os.h | 701 +++++++++++ .../os/linux/src/common/concurrent_os.cpp | 211 ++++ .../os/linux/src/common/platform_utils.cpp | 143 +++ .../win/include/ignite/odbc/common/common.h | 46 + .../ignite/odbc/common/concurrent_os.h | 610 +++++++++ src/odbc/os/win/src/common/concurrent_os.cpp | 208 ++++ src/odbc/os/win/src/common/platform_utils.cpp | 140 +++ src/odbc/os/win/src/system/ui/window.cpp | 8 +- src/odbc/src/app/application_data_buffer.cpp | 2 +- src/odbc/src/common/big_integer.cpp | 866 +++++++++++++ src/odbc/src/common/bits.cpp | 236 ++++ src/odbc/src/common/concurrent.cpp | 108 ++ src/odbc/src/common/decimal.cpp | 278 +++++ src/odbc/src/common/utils.cpp | 219 ++++ src/odbc/src/connection.cpp | 387 +++--- src/odbc/src/ignite_error.cpp | 227 ++++ src/odbc/src/jni/java.cpp | 1102 +++++++++++++++++ src/odbc/src/jni/os/linux/utils.cpp | 432 +++++++ src/odbc/src/jni/os/win/utils.cpp | 459 +++++++ src/odbc/src/log.cpp | 2 +- src/odbc/src/protocol_version.cpp | 2 +- src/odbc/src/ssl_mode.cpp | 2 +- src/odbc/src/utility.cpp | 10 +- 64 files changed, 11498 insertions(+), 475 deletions(-) create mode 100644 scripts/register_driver_macos.sh create mode 100644 src/odbc-test/config/ssh_config create mode 100644 src/odbc/include/ignite/odbc/common/big_integer.h create mode 100644 src/odbc/include/ignite/odbc/common/bits.h create mode 100644 src/odbc/include/ignite/odbc/common/concurrent.h create mode 100644 src/odbc/include/ignite/odbc/common/decimal.h create mode 100644 src/odbc/include/ignite/odbc/common/default_allocator.h create mode 100644 src/odbc/include/ignite/odbc/common/dynamic_size_array.h create mode 100644 src/odbc/include/ignite/odbc/common/expected.h create mode 100644 src/odbc/include/ignite/odbc/common/fixed_size_array.h create mode 100644 src/odbc/include/ignite/odbc/common/platform_utils.h create mode 100644 src/odbc/include/ignite/odbc/common/utils.h create mode 100644 src/odbc/include/ignite/odbc/ignite_error.h create mode 100644 src/odbc/include/ignite/odbc/jni/java.h create mode 100644 src/odbc/include/ignite/odbc/jni/utils.h create mode 100644 src/odbc/os/linux/include/ignite/odbc/common/common.h create mode 100644 src/odbc/os/linux/include/ignite/odbc/common/concurrent_os.h create mode 100644 src/odbc/os/linux/src/common/concurrent_os.cpp create mode 100644 src/odbc/os/linux/src/common/platform_utils.cpp create mode 100644 src/odbc/os/win/include/ignite/odbc/common/common.h create mode 100644 src/odbc/os/win/include/ignite/odbc/common/concurrent_os.h create mode 100644 src/odbc/os/win/src/common/concurrent_os.cpp create mode 100644 src/odbc/os/win/src/common/platform_utils.cpp create mode 100644 src/odbc/src/common/big_integer.cpp create mode 100644 src/odbc/src/common/bits.cpp create mode 100644 src/odbc/src/common/concurrent.cpp create mode 100644 src/odbc/src/common/decimal.cpp create mode 100644 src/odbc/src/common/utils.cpp create mode 100644 src/odbc/src/ignite_error.cpp create mode 100644 src/odbc/src/jni/java.cpp create mode 100644 src/odbc/src/jni/os/linux/utils.cpp create mode 100644 src/odbc/src/jni/os/win/utils.cpp diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index d3fec3b10..ac7484567 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -11,4 +11,3 @@ jobs: - uses: ZedThree/clang-tidy-review@v0.7.0 id: review continue-on-error: true - diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index 870a2b257..29368f323 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -12,9 +12,19 @@ on: env: CI_OUTPUT_PATH: "ci-output" - ODBC_LIB_PATH: "./build/odbc/lib" - ODBC_BIN_PATH: "./build/odbc/bin" - ODBC_BUILD_PATH: "./build/odbc/build" + ODBC_LIB_PATH: "${{github.workspace}}/build/odbc/lib" + ODBC_BIN_PATH: "${{github.workspace}}/build/odbc/bin" + ODBC_BUILD_PATH: "${{github.workspace}}/build/odbc/build" + DOCUMENTDB_HOME: "${{github.workspace}}/build/odbc/bin" + DOC_DB_KEYPAIR: ${{secrets.DOC_DB_KEYPAIR}} + DOC_DB_USER_NAME: ${{secrets.DOC_DB_USER_NAME}} + DOC_DB_PASSWORD: ${{secrets.DOC_DB_PASSWORD}} + DOC_DB_USER: ${{secrets.DOC_DB_USER}} + DOC_DB_HOST: ${{secrets.DOC_DB_HOST}} + DOC_DB_LOCAL_PORT: 27019 + DOC_DB_REMOTE_PORT: 27017 + DOC_DB_PRIV_KEY_FILE: ~/certs/docdb-sshtunnel.pem + JDBC_DRIVER_VERSION: "1.1.0" jobs: build-mac: @@ -37,6 +47,12 @@ jobs: # with: # name: cppcheck-results # path: cppcheck-results.log + - name: Extract key-pair into file + run: | + mkdir ~/certs + echo "${{env.DOC_DB_KEYPAIR}}" > ${{env.DOC_DB_PRIV_KEY_FILE}} + chmod 400 ${{env.DOC_DB_PRIV_KEY_FILE}} + - name: get-dependencies run: | brew install unixodbc @@ -54,6 +70,10 @@ jobs: # sudo cp ./src/Tests/Tests/odbc-mac.ini /Library/ODBC/odbc.ini # sudo cp ./src/Tests/Tests/odbcinst-mac.ini /Library/ODBC/odbcinst.ini # mkdir ${{ github.workspace }}/odbc-logs + - name: register-odbc-driver + run: | + chmod +x scripts/register_driver_macos.sh + ./scripts/register_driver_macos.sh - name: run-tests run: | ./build/odbc/bin/ignite-odbc-tests diff --git a/.github/workflows/mac-debug-build.yml b/.github/workflows/mac-debug-build.yml index 85468cd26..8d41ff8fb 100644 --- a/.github/workflows/mac-debug-build.yml +++ b/.github/workflows/mac-debug-build.yml @@ -8,6 +8,7 @@ env: ODBC_LIB_PATH: "./build/odbc/lib" ODBC_BIN_PATH: "./build/odbc/bin" ODBC_BUILD_PATH: "./build/odbc/build" + DOCUMENTDB_HOME: "./build/odbc/bin" jobs: build-mac: diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index ee0506351..b02b4b8f5 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -16,45 +16,75 @@ env: ODBC_BIN_PATH: "./build/odbc/bin/Release" ODBC_BUILD_PATH: "./build/odbc/cmake" VCPKG_ROOT: "c:/vcpkg" + DOCUMENTDB_HOME: "./build/odbc/bin/Release" + DOC_DB_KEYPAIR: ${{secrets.DOC_DB_KEYPAIR}} + DOC_DB_USER_NAME: ${{secrets.DOC_DB_USER_NAME}} + DOC_DB_PASSWORD: ${{secrets.DOC_DB_PASSWORD}} + DOC_DB_USER: ${{secrets.DOC_DB_USER}} + DOC_DB_HOST: ${{secrets.DOC_DB_HOST}} + RUN_REMOTE_INTEGRATION_TESTS: ${{ github.event.inputs.testWithoutDocumnetDb && 'false' || 'true' }} + DOC_DB_LOCAL_PORT: 27019 + DOC_DB_REMOTE_PORT: 27017 + DOC_DB_PRIV_KEY_FILE: ~/certs/docdb-sshtunnel.pem + JDBC_DRIVER_VERSION: "1.1.0" jobs: build-windows32: runs-on: windows-latest steps: - uses: actions/checkout@v2 + - name: Get Java distribution uses: actions/setup-java@v2 with: distribution: 'temurin' java-version: '17' architecture: x86 + - name: "Update path for Java" run: | echo "${{ env.JAVA_HOME }}\bin\server" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + - name: "Update path for WIX Toolset" run: | echo "C:\Program Files (x86)\WiX Toolset v3.11\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + - name: Get specific version CMake, v3.20.1 uses: lukka/get-cmake@v3.20.1 + - name: add-msbuild-to-path uses: microsoft/setup-msbuild@v1.0.2 + + - name: Extract key-pair into file + run: | + mkdir -p ~/certs + echo "${{env.DOC_DB_KEYPAIR}}" > ~/certs/docdb-sshtunnel.pem + chmod 400 ~/certs/docdb-sshtunnel.pem + mkdir -p ~/.ssh + copy ./src/odbc-test/config/ssh_config ~/.ssh/config + + #- name: Run SSH tunnel to DocumentDB server + # run: | + # ssh.exe -f -N -i ~/certs/docdb-sshtunnel.pem -L ${{env.DOC_DB_LOCAL_PORT}}:${{secrets.DOC_DB_HOST}}:${{env.DOC_DB_REMOTE_PORT}} ${{secrets.DOC_DB_USER}} + - name: Install dependencies Windows run: vcpkg integrate install; vcpkg install openssl:x86-windows boost-test:x86-windows boost-asio:x86-windows boost-chrono:x86-windows boost-interprocess:x86-windows boost-regex:x86-windows boost-system:x86-windows boost-thread:x86-windows env: VCPKG_ROOT: ${{ env.VCPKG_ROOT }} + - name: configure-and-build-driver run: | .\build_win_release32.ps1 env: OPENSSL_ROOT_DIR: '${{ env.VCPKG_ROOT }}/packages/openssl_x86-windows' - # - name: import-registry - # run: | - # reg import .\src\Tests\Tests\AWSProfileRegistry_Win32.reg - # reg import .\src\Tests\Tests\IAMRegistry_Win32.reg - # mkdir ${{ github.workspace }}\odbc-logs + + - name: register-driver + run: | + .\src\odbc\install\install_amd64.cmd ${{env.ODBC_BIN_PATH}}\ignite.odbc.dll ${{env.ODBC_BIN_PATH}}\ignite.odbc.dll + - name: run-tests run: | - ${{ env.ODBC_BIN_PATH }}/ignite-odbc-tests.exe + ${{env.ODBC_BIN_PATH}}/ignite-odbc-tests.exe # - name: upload-test-report # if: failure() # uses: actions/upload-artifact@v2 @@ -91,39 +121,58 @@ jobs: runs-on: windows-latest steps: - uses: actions/checkout@v2 + - name: Get Java distribution uses: actions/setup-java@v2 with: distribution: 'temurin' java-version: '17' architecture: x64 + - name: "Update path for Java" run: | - echo "${{ env.JAVA_HOME }}\bin\server" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + echo "${{env.JAVA_HOME}}\bin\server" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + - name: "Update path for WIX Toolset" run: | echo "C:\Program Files (x86)\WiX Toolset v3.11\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + - name: Get specific version CMake, v3.20.1 uses: lukka/get-cmake@v3.20.1 + - name: add-msbuild-to-path uses: microsoft/setup-msbuild@v1.0.2 + + - name: Extract key-pair into file + run: | + mkdir -p ~/certs + echo "${{env.DOC_DB_KEYPAIR}}" > ~/certs/docdb-sshtunnel.pem + chmod 400 ~/certs/docdb-sshtunnel.pem + mkdir -p ~/.ssh + copy ./src/odbc-test/config/ssh_config ~/.ssh/config + + #- name: Run SSH tunnel to DocumentDB server + # run: | + # ssh.exe -f -N -i ~/certs/docdb-sshtunnel.pem -L ${{env.DOC_DB_LOCAL_PORT}}:${{secrets.DOC_DB_HOST}}:${{env.DOC_DB_REMOTE_PORT}} ${{secrets.DOC_DB_USER}} + - name: Install dependencies Windows run: vcpkg integrate install; vcpkg install openssl:x64-windows boost-test:x64-windows boost-asio:x64-windows boost-chrono:x64-windows boost-interprocess:x64-windows boost-regex:x64-windows boost-system:x64-windows boost-thread:x64-windows env: - VCPKG_ROOT: ${{ env.VCPKG_ROOT }} + VCPKG_ROOT: ${{env.VCPKG_ROOT}} + - name: configure-and-build-driver run: | .\build_win_release64.ps1 env: - OPENSSL_ROOT_DIR: '${{ env.VCPKG_ROOT }}/packages/openssl_x64-windows' - # - name: import-registry - # run: | - # reg import .\src\Tests\Tests\AWSProfileRegistry.reg - # reg import .\src\Tests\Tests\IAMRegistry.reg - # mkdir ${{ github.workspace }}\odbc-logs + OPENSSL_ROOT_DIR: '${{env.VCPKG_ROOT}}/packages/openssl_x64-windows' + + - name: register-driver + run: | + .\src\odbc\install\install_amd64.cmd ${{env.ODBC_BIN_PATH}}\ignite.odbc.dll + - name: run-tests run: | - ${{ env.ODBC_BIN_PATH }}/ignite-odbc-tests.exe + ${{env.ODBC_BIN_PATH}}/ignite-odbc-tests.exe # - name: upload-test-report # if: failure() # uses: actions/upload-artifact@v2 diff --git a/README.md b/README.md index cb1308e83..7db369e0d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,13 @@ 1. E.g.: `.\build_win_debug64.ps1` 2. Navigate to the `build\odbc\cmake` folder to use the generated solution file, `Ignite.C++.sln` to work on source code development and testing. -7. More details in `src\DEVNOTES.txt`. +7. Set the environment variable `DOCUMENTDB_HOME`. On a developer's machine, set it to `\build\odbc\bin\Debug`. The + build script run above, downloads it to the `\build\odbc\bin\Debug\libs` folder. +8. Open a **64-bit** command shell or **64-bit** PowerShell window, **as Administrator**, run the + ``` + \src\odbc\src\install\install_amd64.cmd \buildbuild\odbc\cmake\Debug\ignite.odbc.dll + ``` +8. More details in [`src\DEVNOTES.txt`](src/DEVNOTES.txt). ### MacOS @@ -44,7 +50,7 @@ 2. Run one of the build scripts to create an initial compilation. 1. E.g.: `./build_mac_release64.sh` 2. Navigate to the `build/odbc/lib` folder to use the generated files. -3. More details in `src\DEVNOTES.txt`. +3. More details in [`src\DEVNOTES.txt`](src/DEVNOTES.txt). ### Linux diff --git a/build_mac_debug64.sh b/build_mac_debug64.sh index 98222f20f..1118a04b9 100755 --- a/build_mac_debug64.sh +++ b/build_mac_debug64.sh @@ -1,5 +1,26 @@ + +BUILD_DIR=cmake-build64 +BUILD_TYPE=Debug +PROJECT_DIR=$(pwd) +DRIVER_BIN_DIR="$PROJECT_DIR/build/odbc/bin" + mkdir cmake-build64 cd cmake-build64 cmake ../src -DCMAKE_BUILD_TYPE="Debug" -DCODE_COVERAGE="ON" -DBUILD_SHARED_LIBS="OFF" -DWITH_TESTS="ON" -DWITH_CORE="OFF" -DWITH_ODBC="ON" +cd .. + +# Download the DocumentDB JDBC Driver +JDBC_DRIVER_VERSION="${JDBC_DRIVER_VERSION-1.1.0}" +JDBC_DRIVER_FILENAME="documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" +JDBC_DRIVER_FULLPATH="$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" +export DOCUMENTDB_HOME="$DRIVER_BIN_DIR" +if [ ! -f "$JDBC_DRIVER_FULLPATH" ]; then + mkdir "$DRIVER_BIN_DIR/libs" + echo "Downloading version $JDBC_DRIVER_VERSION of JDBC driver..." + curl -o "$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" -L https://github.com/aws/amazon-documentdb-jdbc-driver/releases/download/v$JDBC_DRIVER_VERSION/$JDBC_DRIVER_FILENAME + echo "Download complete." +fi + +cd cmake-build64 make ccov-all -j 4 cd .. diff --git a/build_mac_release64.sh b/build_mac_release64.sh index b2f6bb36f..ca42d942e 100755 --- a/build_mac_release64.sh +++ b/build_mac_release64.sh @@ -1,5 +1,25 @@ -mkdir cmake-build64 -cd cmake-build64 -cmake ../src -DCMAKE_BUILD_TYPE="Release" -DCODE_COVERAGE="OFF" -DBUILD_SHARED_LIBS="OFF" -DWITH_TESTS="ON" -DWITH_CORE="OFF" -DWITH_ODBC="ON" + +BUILD_DIR=cmake-build64 +BUILD_TYPE=Release +PROJECT_DIR=$(pwd) +DRIVER_BIN_DIR="$PROJECT_DIR/build/odbc/bin" + +set -e +mkdir $BUILD_DIR +cd $BUILD_DIR +cmake ../src -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCODE_COVERAGE="OFF" -DBUILD_SHARED_LIBS="OFF" -DWITH_TESTS="ON" -DWITH_CORE="OFF" -DWITH_ODBC="ON" make -j 4 + +# Download the DocumentDB JDBC Driver +JDBC_DRIVER_VERSION="${JDBC_DRIVER_VERSION-1.1.0}" +JDBC_DRIVER_FILENAME="documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" +JDBC_DRIVER_FULLPATH="$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" +export DOCUMENTDB_HOME="$DRIVER_BIN_DIR" +if [ ! -f "$JDBC_DRIVER_FULLPATH" ]; then + mkdir "$DRIVER_BIN_DIR/libs" + echo "Downloading version $JDBC_DRIVER_VERSION of JDBC driver..." + curl -o "$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" -L https://github.com/aws/amazon-documentdb-jdbc-driver/releases/download/v$JDBC_DRIVER_VERSION/$JDBC_DRIVER_FILENAME + echo "Download complete." +fi + cd .. diff --git a/scripts/build_windows.ps1 b/scripts/build_windows.ps1 index 3e3d72988..3118170cf 100644 --- a/scripts/build_windows.ps1 +++ b/scripts/build_windows.ps1 @@ -28,6 +28,21 @@ Set-Location $CURRENT_DIR $DRIVER_BIN_DIR = "$DRIVER_BUILD_DIR\..\bin\$CONFIGURATION" New-Item -Path $DRIVER_BIN_DIR -ItemType Directory -Force | Out-Null +# Download the JDBC driver +$JDBC_DRIVER_VERSION = if ($JDBC_DRIVER_VERSION -eq $null) { "1.1.0" } else { $JDBC_DRIVER_VERSION } +$JDBC_DRIVER_FILENAME = "documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" +$JDBC_DRIVER_FULLPATH = "$DRIVER_BIN_DIR\libs\$JDBC_DRIVER_FILENAME" +if (-not (Test-Path -Path $JDBC_DRIVER_FULLPATH -PathType Leaf)) { + New-Item -Path "$DRIVER_BIN_DIR\libs" -ItemType Directory -Force | Out-Null + Write-Output "Downloading version $JDBC_DRIVER_VERSION of JDBC driver..." + $progresspreference = 'silentlyContinue' + Invoke-WebRequest ` + https://github.com/aws/amazon-documentdb-jdbc-driver/releases/download/v$JDBC_DRIVER_VERSION/$JDBC_DRIVER_FILENAME ` + -o $JDBC_DRIVER_FULLPATH + $progressPreference = 'Continue' + Write-Output "Download complete." +} + if (Test-Path -Path $DRIVER_BUILD_DIR\$CONFIGURATION) { Copy-Item $DRIVER_BUILD_DIR\$CONFIGURATION\* $DRIVER_BIN_DIR } diff --git a/scripts/register_driver_macos.sh b/scripts/register_driver_macos.sh new file mode 100644 index 000000000..a5f4f6005 --- /dev/null +++ b/scripts/register_driver_macos.sh @@ -0,0 +1,27 @@ + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done + +SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + +PROJECT_DIR="$SCRIPT_DIR/.." +ODBC_LIB_PATH="$PROJECT_DIR/build/odbc/lib" +ODBC_LIB_FILENAME="$ODBC_LIB_PATH/libignite-odbc.dylib" + +if [ ! -f "$ODBC_LIB_FILENAME" ] +then + echo "Cannot find ODBC library file: $ODBC_LIB_FILENAME" + exit 1 +fi + +echo "[Apache Ignite]" > "$ODBC_LIB_PATH/ignite-odbc-install.ini" +echo "Description=Apache Ignite" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" +echo "Driver=$ODBC_LIB_FILENAME" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" +echo "Setup=$ODBC_LIB_FILENAME" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" +echo "DriverODBCVer=03.00" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" +echo "FileUsage=0" >> "$ODBC_LIB_PATH/ignite-odbc-install.ini" +odbcinst -i -d -f "$ODBC_LIB_PATH/ignite-odbc-install.ini" diff --git a/src/common/include/ignite/common/big_integer.h b/src/common/include/ignite/common/big_integer.h index 699f59e38..66aef6db0 100644 --- a/src/common/include/ignite/common/big_integer.h +++ b/src/common/include/ignite/common/big_integer.h @@ -383,7 +383,7 @@ namespace ignite // Reading number itself. while (is && isdigit(c)) { - part = part * 10 + (c - '0'); + part = part * 10 + (static_cast(c) - '0'); ++partDigits; if (part >= 1000000000000000000U) diff --git a/src/common/include/ignite/common/decimal.h b/src/common/include/ignite/common/decimal.h index d45297a29..39287264e 100644 --- a/src/common/include/ignite/common/decimal.h +++ b/src/common/include/ignite/common/decimal.h @@ -326,7 +326,7 @@ namespace ignite os << '0'; } - os.write(&magStr[magBegin], lastNonZero - magBegin + 1); + os.write(&magStr[magBegin], static_cast(lastNonZero) - magBegin + 1); } else { @@ -340,7 +340,7 @@ namespace ignite { os << '.'; - os.write(&magStr[magBegin + dotPos], afterDot); + os.write(&magStr[static_cast< std::basic_string< char, std::char_traits< char >, std::allocator< char > >::size_type >(magBegin) + dotPos], afterDot); } } @@ -395,7 +395,7 @@ namespace ignite { if (isdigit(c)) { - part = part * 10 + (c - '0'); + part = part * 10 + (static_cast(c) - '0'); ++partDigits; } else if (c == '.' && scale < 0) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index f81e1a103..77294465b 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -29,29 +29,27 @@ find_package(ODBC REQUIRED) include_directories(SYSTEM ${ODBC_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${JNI_INCLUDE_DIRS}) include_directories(include ../odbc/include ../network/include) +if (WIN32) + include_directories(../odbc/os/win/include) +else () + # TODO: Ensure MacOS is portable. https://bitquill.atlassian.net/browse/AD-525 + include_directories(../odbc/os/linux/include) +endif() set(SOURCES + src/connection_test.cpp src/dummy_test.cpp - src/configuration_test.cpp - ../odbc/src/config/config_tools.cpp - ../odbc/src/config/configuration.cpp - ../odbc/src/config/connection_info.cpp - ../odbc/src/config/connection_string_parser.cpp - ../odbc/src/scan_method.cpp - ../odbc/src/read_preference.cpp - ../odbc/src/diagnostic/diagnostic_record.cpp - ../odbc/src/diagnostic/diagnostic_record_storage.cpp - ../odbc/src/utility.cpp - ../odbc/src/common_types.cpp - ../odbc/src/app/application_data_buffer.cpp - ../odbc/src/log.cpp + src/odbc_test_suite.cpp + src/test_utils.cpp + ../odbc/src/common/concurrent.cpp + ../odbc/src/common/utils.cpp + ../odbc/src/jni/java.cpp # TODO uncomment/rework the tests after get some connectivity and functionalities working. # src/teamcity/teamcity_boost.cpp # src/teamcity/teamcity_messages.cpp # src/parser_test.cpp # src/cursor_test.cpp # src/connection_info_test.cpp -# src/connection_test.cpp # src/application_data_buffer_test.cpp # src/column_test.cpp # src/configuration_test.cpp @@ -60,7 +58,6 @@ set(SOURCES # src/utility_test.cpp # src/queries_test.cpp # src/queries_ssl_test.cpp -# src/test_utils.cpp # src/sql_test_suite_fixture.cpp # src/sql_string_functions_test.cpp # src/sql_numeric_functions_test.cpp @@ -76,7 +73,6 @@ set(SOURCES # src/api_robustness_test.cpp # src/attributes_test.cpp # src/errors_test.cpp -# src/odbc_test_suite.cpp # src/types_test.cpp # src/transaction_test.cpp # src/authentication_test.cpp @@ -107,6 +103,21 @@ set(SOURCES # ../odbc/src/nested_tx_mode.cpp ) +if (WIN32) + list(APPEND SOURCES + ../odbc/os/win/src/common/concurrent_os.cpp + ../odbc/os/win/src/common/platform_utils.cpp + ../odbc/src/jni/os/win/utils.cpp + ) +else() + # TODO: Ensure MacOS is portable. https://bitquill.atlassian.net/browse/AD-525 + list(APPEND SOURCES + ../odbc/os/linux/src/common/concurrent_os.cpp + ../odbc/os/linux/src/common/platform_utils.cpp + ../odbc/src/jni/os/linux/utils.cpp + ) +endif() + add_executable(${TARGET} ${SOURCES}) target_link_libraries(${TARGET} ${Boost_LIBRARIES} ignite ${ODBC_LIBRARY}) diff --git a/src/odbc-test/config/ssh_config b/src/odbc-test/config/ssh_config new file mode 100644 index 000000000..6318ba0a5 --- /dev/null +++ b/src/odbc-test/config/ssh_config @@ -0,0 +1,2 @@ +Host * + StrictHostKeyChecking no diff --git a/src/odbc-test/include/odbc_test_suite.h b/src/odbc-test/include/odbc_test_suite.h index 1bdd3b077..6bd00a63a 100644 --- a/src/odbc-test/include/odbc_test_suite.h +++ b/src/odbc-test/include/odbc_test_suite.h @@ -75,7 +75,9 @@ namespace ignite * @param connectStr Connection string. * @return SQL State. */ - std::string ExpectConnectionReject(const std::string& connectStr); + std::string ExpectConnectionReject( + const std::string& connectStr, + const std::string& expectedError = "08001: Failed to establish connection with the host."); /** * Disconnect. @@ -87,14 +89,6 @@ namespace ignite */ void CleanUp(); - /** - * Start additional with the specified name and config. - * - * @param cfg Config path. - * @param name Instance name. - */ - static Ignite StartTestNode(const char* cfg, const char* name); - /** * Constructor. */ diff --git a/src/odbc-test/include/test_utils.h b/src/odbc-test/include/test_utils.h index f83b23b0c..dc7b01a80 100644 --- a/src/odbc-test/include/test_utils.h +++ b/src/odbc-test/include/test_utils.h @@ -27,7 +27,7 @@ #include -#include "ignite/ignition.h" +#include "ignite/odbc/common/utils.h" #define ODBC_THROW_ON_ERROR(ret, type, handle) \ if (!SQL_SUCCEEDED(ret)) \ @@ -160,51 +160,6 @@ namespace ignite_test */ std::string GetTestConfigDir(); - /** - * Initialize configuration for a node. - * - * Inits Ignite node configuration from specified config file. - * Config file is searched in path specified by IGNITE_NATIVE_TEST_CPP_CONFIG_PATH - * environmental variable. - * - * @param cfg Ignite config. - * @param cfgFile Ignite node config file name without path. - */ - void InitConfig(ignite::IgniteConfiguration& cfg, const char* cfgFile); - - /** - * Start Ignite node. - * - * Starts new Ignite node from specified config file. - * Config file is searched in path specified by IGNITE_NATIVE_TEST_CPP_CONFIG_PATH - * environmental variable. - * - * @param cfgFile Ignite node config file name without path. - * @return New node. - */ - ignite::Ignite StartNode(const char* cfgFile); - - /** - * Start Ignite node. - * - * Starts new Ignite node with the specified name and from specified config file. - * Config file is searched in path specified by IGNITE_NATIVE_TEST_CPP_CONFIG_PATH - * environmental variable. - * - * @param cfgFile Ignite node config file name without path. - * @param name Node name. - * @return New node. - */ - ignite::Ignite StartNode(const char* cfgFile, const char* name); - - /** - * Start node with the config for the current platform. - * - * @param cfg Basic config path. Changed to platform config if needed. - * @param name Instance name. - */ - ignite::Ignite StartPlatformNode(const char* cfg, const char* name); - /** * Remove all the LFS artifacts. */ diff --git a/src/odbc-test/src/connection_test.cpp b/src/odbc-test/src/connection_test.cpp index 6d4ed9a8e..28714a040 100644 --- a/src/odbc-test/src/connection_test.cpp +++ b/src/odbc-test/src/connection_test.cpp @@ -15,7 +15,6 @@ * limitations under the License. */ -#include "test_server.h" #ifdef _WIN32 # include #endif @@ -27,14 +26,10 @@ #include -#include "ignite/ignite.h" -#include "ignite/ignition.h" - #include "test_utils.h" #include "odbc_test_suite.h" using namespace ignite; -using namespace ignite::common; using namespace ignite_test; using namespace boost::unit_test; @@ -53,14 +48,6 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite // No-op. } - /** - * Start a node. - */ - void StartNode() - { - StartTestNode("queries-test.xml", "NodeMain"); - } - /** * Execute the query and return an error code. */ @@ -96,6 +83,25 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite return code; } + static void SetConnectionString(std::string& connectionString, + const std::string& username = std::string()) { + // NOTE: Assuming we are using internal SSH tunnel + std::string user = common::GetEnv("DOC_DB_USER_NAME", "documentdb"); + std::string password = common::GetEnv("DOC_DB_PASSWORD", ""); + std::string host = common::GetEnv("DOC_DB_HOST", ""); + std::string port = "27017"; + if (!username.empty()) { + user = username; + } + + connectionString = + "DRIVER={Apache Ignite};" + "ADDRESS=" + host + ":" + port + ";" + "SCHEMA=test;" + "USER=" + user + ";" + "PASSWORD=" + password + ";"; + } + /** * Destructor. */ @@ -105,44 +111,60 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite } }; + BOOST_FIXTURE_TEST_SUITE(ConnectionTestSuite, ConnectionTestSuiteFixture) BOOST_AUTO_TEST_CASE(TestConnectionRestore) { - StartNode(); + std::string connectionString; + SetConnectionString(connectionString); - Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache"); + Connect(connectionString); + Disconnect(); - // Check that query was successfully executed. - BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); + // TODO: [AD-507] Re-enable when querying is supported. + // https://bitquill.atlassian.net/browse/AD-507 - // Stop node. - Ignition::StopAll(true); + //// Check that query was successfully executed. + //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); - // Query execution should throw ODBC error. - BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08S01"); + //// Query execution should throw ODBC error. + //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08S01"); - // Reusing a closed connection should not crash an application. - BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08001"); + //// Reusing a closed connection should not crash an application. + //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08001"); - StartNode(); + //// Check that connection was restored. + //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); - // Check that connection was restored. - BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); } BOOST_AUTO_TEST_CASE(TestConnectionMemoryLeak) { - TestServer testServer(11100); + std::string connectionString; + SetConnectionString(connectionString); - testServer.PushHandshakeResponse(true); - testServer.Start(); + Connect(connectionString); - Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11100;SCHEMA=cache"); - - ExecQuery("Select * from Test"); + // TODO: [AD-507] Re-enable when querying is supported. + // https://bitquill.atlassian.net/browse/AD-507 + // ExecQuery("Select * from Test"); Disconnect(); +} + +BOOST_AUTO_TEST_CASE(TestConnectionInvalidUser) { + std::string connectionString; + SetConnectionString(connectionString, "invaliduser"); + + ExpectConnectionReject(connectionString, "08001: Failed to establish connection with the host.\n" + "Invalid username or password or user is not authorized on database 'test'. " + "Please check your settings. Authorization failed for user 'invaliduser' on database 'admin' with mechanism"); + + // TODO: [AD-507] Re-enable when querying is supported. + // https://bitquill.atlassian.net/browse/AD-507 + // ExecQuery("Select * from Test"); + Disconnect(); } diff --git a/src/odbc-test/src/odbc_test_suite.cpp b/src/odbc-test/src/odbc_test_suite.cpp index bef4639e1..1b2ece743 100644 --- a/src/odbc-test/src/odbc_test_suite.cpp +++ b/src/odbc-test/src/odbc_test_suite.cpp @@ -24,10 +24,9 @@ #include -#include "ignite/ignition.h" - #include "test_utils.h" #include "odbc_test_suite.h" +#include using namespace ignite_test; using namespace boost::unit_test; @@ -103,7 +102,9 @@ namespace ignite BOOST_REQUIRE(stmt != NULL); } - std::string OdbcTestSuite::ExpectConnectionReject(const std::string& connectStr) + std::string OdbcTestSuite::ExpectConnectionReject( + const std::string& connectStr, + const std::string& expectedError) { Prepare(); @@ -118,6 +119,9 @@ namespace ignite outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); BOOST_REQUIRE_EQUAL(ret, SQL_ERROR); + BOOST_REQUIRE_EQUAL(expectedError, + GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc) + .substr(0, expectedError.size())); return GetOdbcErrorState(SQL_HANDLE_DBC, dbc); } @@ -154,19 +158,6 @@ namespace ignite } } - Ignite OdbcTestSuite::StartTestNode(const char* cfg, const char* name) - { - std::string config(cfg); - -#ifdef IGNITE_TESTS_32 - // Cutting off the ".xml" part. - config.resize(config.size() - 4); - config += "-32.xml"; -#endif //IGNITE_TESTS_32 - - return StartNode(config.c_str(), name); - } - OdbcTestSuite::OdbcTestSuite(): env(NULL), dbc(NULL), @@ -178,8 +169,6 @@ namespace ignite OdbcTestSuite::~OdbcTestSuite() { CleanUp(); - - Ignition::StopAll(true); } int8_t OdbcTestSuite::GetTestI8Field(int64_t idx) @@ -347,7 +336,7 @@ namespace ignite { BOOST_TEST_CONTEXT("Test index: " << idx) { - common::FixedSizeArray expected(static_cast(valLen)); + odbc::common::FixedSizeArray expected(static_cast(valLen)); GetTestI8ArrayField(idx, expected.GetData(), expected.GetSize()); for (size_t j = 0; j < valLen; ++j) diff --git a/src/odbc-test/src/test_utils.cpp b/src/odbc-test/src/test_utils.cpp index bdd32d8af..aa4e654b5 100644 --- a/src/odbc-test/src/test_utils.cpp +++ b/src/odbc-test/src/test_utils.cpp @@ -19,10 +19,13 @@ #include -#include +#include +#include "ignite/odbc/jni/utils.h" + #include "test_utils.h" + namespace ignite_test { OdbcClientError GetOdbcError(SQLSMALLINT handleType, SQLHANDLE handle) @@ -75,14 +78,14 @@ namespace ignite_test std::string GetTestConfigDir() { - using namespace ignite; + using namespace ignite::odbc; std::string cfgPath = common::GetEnv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH"); if (!cfgPath.empty()) return cfgPath; - std::string home = jni::ResolveIgniteHome(); + std::string home = jni::ResolveDocumentDbHome(); if (home.empty()) return home; @@ -99,100 +102,20 @@ namespace ignite_test return path.str(); } - void InitConfig(ignite::IgniteConfiguration& cfg, const char* cfgFile) - { - using namespace ignite; - - assert(cfgFile != 0); - - cfg.jvmOpts.push_back("-Xdebug"); - cfg.jvmOpts.push_back("-Xnoagent"); - cfg.jvmOpts.push_back("-Djava.compiler=NONE"); - cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"); - cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError"); - cfg.jvmOpts.push_back("-Duser.timezone=GMT"); - cfg.jvmOpts.push_back("-DIGNITE_QUIET=false"); - cfg.jvmOpts.push_back("-DIGNITE_CONSOLE_APPENDER=false"); - cfg.jvmOpts.push_back("-DIGNITE_UPDATE_NOTIFIER=false"); - cfg.jvmOpts.push_back("-DIGNITE_LOG_CLASSPATH_CONTENT_ON_STARTUP=false"); - cfg.jvmOpts.push_back("-Duser.language=en"); - // Un-comment to debug SSL - //cfg.jvmOpts.push_back("-Djavax.net.debug=ssl"); - - cfg.igniteHome = jni::ResolveIgniteHome(); - cfg.jvmClassPath = jni::CreateIgniteHomeClasspath(cfg.igniteHome, true); - -#ifdef IGNITE_TESTS_32 - cfg.jvmInitMem = 256; - cfg.jvmMaxMem = 768; -#else - cfg.jvmInitMem = 1024; - cfg.jvmMaxMem = 4096; -#endif - - std::string cfgDir = GetTestConfigDir(); - - if (cfgDir.empty()) - throw IgniteError(IgniteError::IGNITE_ERR_GENERIC, "Failed to resolve test config directory"); - - std::stringstream path; - - path << cfgDir << common::Fs << cfgFile; - - cfg.springCfgPath = path.str(); - } - - ignite::Ignite StartNode(const char* cfgFile) - { - using namespace ignite; - - IgniteConfiguration cfg; - - InitConfig(cfg, cfgFile); - - return Ignition::Start(cfg); - } - - ignite::Ignite StartNode(const char* cfgFile, const char* name) - { - using namespace ignite; - - assert(name != 0); - - IgniteConfiguration cfg; - - InitConfig(cfg, cfgFile); - - return Ignition::Start(cfg, name); - } - - ignite::Ignite StartPlatformNode(const char* cfg, const char* name) - { - std::string config(cfg); - -#ifdef IGNITE_TESTS_32 - // Cutting off the ".xml" part. - config.resize(config.size() - 4); - config += "-32.xml"; -#endif //IGNITE_TESTS_32 - - return StartNode(config.c_str(), name); - } - std::string AppendPath(const std::string& base, const std::string& toAdd) { std::stringstream stream; - stream << base << ignite::common::Fs << toAdd; + stream << base << ignite::odbc::common::Fs << toAdd; return stream.str(); } void ClearLfs() { - std::string home = ignite::jni::ResolveIgniteHome(); + std::string home = ignite::odbc::jni::ResolveDocumentDbHome(); std::string workDir = AppendPath(home, "work"); - ignite::common::DeletePath(workDir); + ignite::odbc::common::DeletePath(workDir); } } diff --git a/src/odbc/CMakeLists.txt b/src/odbc/CMakeLists.txt index e2021f3e7..0c6c45caa 100644 --- a/src/odbc/CMakeLists.txt +++ b/src/odbc/CMakeLists.txt @@ -20,14 +20,23 @@ project(ignite-odbc) set(TARGET ${PROJECT_NAME}) find_package(ODBC REQUIRED) +find_package(Java REQUIRED) +find_package(JNI REQUIRED) +include(UseJava) -include_directories(SYSTEM ${ODBC_INCLUDE_DIRS}) +include_directories(SYSTEM ${ODBC_INCLUDE_DIRS} ${JNI_INCLUDE_DIRS}) include_directories(include) set(SOURCES src/app/application_data_buffer.cpp src/app/parameter.cpp src/app/parameter_set.cpp src/common_types.cpp + src/common/big_integer.cpp + src/common/bits.cpp + src/common/concurrent.cpp + src/common/decimal.cpp + src/ignite_error.cpp + src/common/utils.cpp src/config/config_tools.cpp src/config/configuration.cpp src/config/connection_info.cpp @@ -37,6 +46,7 @@ set(SOURCES src/app/application_data_buffer.cpp src/diagnostic/diagnosable_adapter.cpp src/diagnostic/diagnostic_record.cpp src/diagnostic/diagnostic_record_storage.cpp + src/jni/java.cpp src/environment.cpp src/meta/column_meta.cpp src/meta/table_meta.cpp @@ -73,20 +83,37 @@ set(SOURCES src/app/application_data_buffer.cpp src/scan_method.cpp) if (WIN32) - include_directories(os/win/include) + set(OS_INCLUDE os/win/include) - list(APPEND SOURCES os/win/src/system_dsn.cpp + list(APPEND SOURCES + os/win/src/system_dsn.cpp os/win/src/system/ui/custom_window.cpp os/win/src/system/ui/dsn_configuration_window.cpp os/win/src/system/ui/window.cpp - module.def) + os/win/src/common/concurrent_os.cpp + os/win/src/common/platform_utils.cpp + src/jni/os/win/utils.cpp + module.def + ) +else() + set(OS_INCLUDE os/linux/include) + + list(APPEND SOURCES + os/linux/src/common/concurrent_os.cpp + os/linux/src/common/platform_utils.cpp + src/jni/os/linux/utils.cpp + ) endif () +include_directories(${OS_INCLUDE}) + + add_library(${TARGET} SHARED ${SOURCES}) set_target_properties(${TARGET} PROPERTIES VERSION ${CMAKE_PROJECT_VERSION}) target_link_libraries(${TARGET} ${ODBC_LIBRARIES}) +target_link_libraries(${TARGET} ${JNI_LIBRARIES}) if (WIN32) target_link_libraries(${TARGET} ignite-common-objlib ignite-binary-objlib ignite-network-objlib odbccp32 shlwapi) diff --git a/src/odbc/include/ignite/odbc/app/application_data_buffer.h b/src/odbc/include/ignite/odbc/app/application_data_buffer.h index 50d324488..af0231b46 100644 --- a/src/odbc/include/ignite/odbc/app/application_data_buffer.h +++ b/src/odbc/include/ignite/odbc/app/application_data_buffer.h @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include "ignite/odbc/common_types.h" #include "ignite/odbc/type_traits.h" diff --git a/src/odbc/include/ignite/odbc/common/big_integer.h b/src/odbc/include/ignite/odbc/common/big_integer.h new file mode 100644 index 000000000..4e06543a3 --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/big_integer.h @@ -0,0 +1,526 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_COMMON_BIG_INTEGER +#define _IGNITE_ODBC_COMMON_BIG_INTEGER + +#include + +#include +#include + +#include + +namespace ignite +{ + namespace odbc + { + namespace common + { + /** + * Big integer number implementation. + */ + class IGNITE_IMPORT_EXPORT BigInteger + { + friend class Decimal; + public: + // Magnitude array type. + typedef DynamicSizeArray MagArray; + + /** + * Default constructor. Constructs zero-value big integer. + */ + BigInteger(); + + /** + * Constructs big integer with the specified integer value. + * + * @param val Value. + */ + explicit BigInteger(int64_t val); + + /** + * String constructor. + * + * @param val String to assign. + * @param len String length. + */ + BigInteger(const char* val, int32_t len); + + /** + * String constructor. + * + * @param val String to assign. + */ + explicit BigInteger(const std::string& val) : + sign(1), + mag() + { + AssignString(val); + } + + /** + * Copy constructor. + * + * @param other Other value. + */ + BigInteger(const BigInteger& other); + + /** + * Constructs big integer from the byte array. + * + * @param val Bytes of the integer. Byte order is big-endian. + * @param len Array length. + * @param sign Signum. Can be -1 (negative) or 1 (positive or zero). + * @param bigEndian If true then magnitude is in big-endian. Otherwise + * the byte order of the magnitude considered to be little-endian. + */ + BigInteger(const int8_t* val, int32_t len, int32_t sign, bool bigEndian = true); + + /** + * Constructs big integer with the specified magnitude. + * @warning Magnitude is moved. This mean mag left empty after the call. + * + * @param mag Magnitude. Moved. + * @param sign Sign. Can be 1 or -1. + */ + BigInteger(MagArray& mag, int8_t sign); + + /** + * Assigment operator. + * + * @param other Other value. + * @return *this. + */ + BigInteger& operator=(const BigInteger& other); + + /** + * Assign specified value to this BigInteger. + * + * @param val Value to assign. + */ + void Assign(const BigInteger& val); + + /** + * Assign specified value to this BigInteger. + * + * @param val Value to assign. + */ + void AssignInt64(int64_t val); + + /** + * Assign specified value to this Decimal. + * + * @param val String to assign. + */ + void AssignString(const std::string& val) + { + AssignString(val.data(), static_cast(val.size())); + } + + /** + * Assign specified value to this Decimal. + * + * @param val String to assign. + * @param len String length. + */ + void AssignString(const char* val, int32_t len); + + /** + * Assign specified value to this BigInteger. + * + * @param val Value to assign. + */ + void AssignUint64(uint64_t val); + + /** + * Get number sign. Returns -1 if negative and 1 otherwise. + * + * @return Sign of the number. + */ + int8_t GetSign() const; + + /** + * Swap function for the BigInteger type. + * + * @param other Other instance. + */ + void Swap(BigInteger& other); + + /** + * Get magnitude array. + * + * @return magnitude array. + */ + const MagArray& GetMagnitude() const; + + /** + * Get this number length in bits as if it was positive. + * + * @return Number length in bits. + */ + uint32_t GetBitLength() const; + + /** + * Get precision of the BigInteger. + * + * @return Number of the decimal digits in the decimal representation + * of the value. + */ + int32_t GetPrecision() const; + + /** + * Fills specified buffer with data of this BigInteger converted to + * bytes in big-endian byte order. Sign is not considered when this + * operation is performed. + * + * @param buffer Buffer to fill. + */ + void MagnitudeToBytes(common::FixedSizeArray& buffer) const; + + /** + * Mutates this BigInteger so its value becomes exp power of this. + * + * @param exp Exponent. + */ + void Pow(int32_t exp); + + /** + * Muitiply this to another big integer. + * + * @param other Another instance. Can be *this. + * @param res Result placed there. Can be *this. + */ + void Multiply(const BigInteger& other, BigInteger& res) const; + + /** + * Divide this to another big integer. + * + * @param divisor Divisor. Can be *this. + * @param res Result placed there. Can be *this. + */ + void Divide(const BigInteger& divisor, BigInteger& res) const; + + /** + * Divide this to another big integer. + * + * @param divisor Divisor. Can be *this. + * @param res Result placed there. Can be *this. + * @param rem Remainder placed there. Can be *this. + */ + void Divide(const BigInteger& divisor, BigInteger& res, BigInteger& rem) const; + + /** + * Add unsigned integer number to this BigInteger. + * + * @param x Number to add. + */ + void Add(uint64_t x); + + /** + * Compare this instance to another. + * + * @param other Another instance. + * @param ignoreSign If set to true than only magnitudes are compared. + * @return Comparasion result - 0 if equal, 1 if this is greater, -1 if + * this is less. + */ + int32_t Compare(const BigInteger& other, bool ignoreSign = false) const; + + /** + * Convert to int64_t. + * + * @return int64_t value. + */ + int64_t ToInt64() const; + + /** + * Check whether this value is negative. + * + * @return True if this value is negative and false otherwise. + */ + bool IsNegative() const + { + return sign < 0; + } + + /** + * Check whether this value is zero. + * + * @return True if this value is negative and false otherwise. + */ + bool IsZero() const + { + return mag.GetSize() == 0; + } + + /** + * Check whether this value is positive. + * + * @return True if this value is positive and false otherwise. + */ + bool IsPositive() const + { + return sign > 0 && !IsZero(); + } + + /** + * Rverses sign of this value. + */ + void Negate() + { + if (!IsZero()) + sign = -sign; + } + + /** + * Output operator. + * + * @param os Output stream. + * @param val Value to output. + * @return Reference to the first param. + */ + friend std::ostream& operator<<(std::ostream& os, const BigInteger& val) + { + if (val.IsZero()) + return os << '0'; + + if (val.sign < 0) + os << '-'; + + const int32_t maxResultDigits = 19; + BigInteger maxUintTenPower; + BigInteger res; + BigInteger left; + + maxUintTenPower.AssignUint64(10000000000000000000U); + + std::vector vals; + + val.Divide(maxUintTenPower, left, res); + + if (res.sign < 0) + res.sign = -res.sign; + + if (left.sign < 0) + left.sign = -left.sign; + + vals.push_back(static_cast(res.ToInt64())); + + while (!left.IsZero()) + { + left.Divide(maxUintTenPower, left, res); + + vals.push_back(static_cast(res.ToInt64())); + } + + os << vals.back(); + + for (int32_t i = static_cast(vals.size()) - 2; i >= 0; --i) + { + os.fill('0'); + os.width(maxResultDigits); + + os << vals[i]; + } + + return os; + } + + /** + * Input operator. + * + * @param is Input stream. + * @param val Value to input. + * @return Reference to the first param. + */ + friend std::istream& operator>>(std::istream& is, BigInteger& val) + { + std::istream::sentry sentry(is); + + // Return zero if input failed. + val.AssignInt64(0); + + if (!is) + return is; + + // Current value parts. + uint64_t part = 0; + int32_t partDigits = 0; + int32_t sign = 1; + + BigInteger pow; + BigInteger bigPart; + + // Current char. + int c = is.peek(); + + if (!is) + return is; + + // Checking sign. + if (c == '-' || c == '+') + { + if (c == '-') + sign = -1; + + is.ignore(); + c = is.peek(); + } + + // Reading number itself. + while (is && isdigit(c)) + { + part = part * 10 + (static_cast(c) - '0'); + ++partDigits; + + if (part >= 1000000000000000000U) + { + BigInteger::GetPowerOfTen(partDigits, pow); + val.Multiply(pow, val); + + val.Add(part); + + part = 0; + partDigits = 0; + } + + is.ignore(); + c = is.peek(); + } + + // Adding last part of the number. + if (partDigits) + { + BigInteger::GetPowerOfTen(partDigits, pow); + + val.Multiply(pow, val); + + val.Add(part); + } + + if (sign < 0) + val.Negate(); + + return is; + } + + /** + * Get BigInteger which value is the ten of the specified power. + * + * @param pow Tenth power. + * @param res Result is placed here. + */ + static void GetPowerOfTen(int32_t pow, BigInteger& res); + + private: + /** + * Add magnitude array to current. + * + * @param addend Addend. + * @param len Length of the addend. + */ + void Add(const uint32_t* addend, int32_t len); + + /** + * Get n-th integer of the magnitude. + * + * @param n Index. + * @return Value of the n-th int of the magnitude. + */ + uint32_t GetMagInt(int32_t n) const; + + /** + * Divide this to another big integer. + * + * @param divisor Divisor. Can be *this. + * @param res Result placed there. Can be *this. + * @param rem Remainder placed there if requested. Can be *this. + * Can be null if the remainder is not needed. + */ + void Divide(const BigInteger& divisor, BigInteger& res, BigInteger* rem) const; + + /** + * Normalizes current value removing trailing zeroes from the magnitude. + */ + void Normalize(); + + /** The sign of this BigInteger: -1 for negative and 1 for non-negative. */ + int8_t sign; + + /** The magnitude of this BigInteger. Byte order is little-endian. */ + MagArray mag; + }; + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if equal. + */ + IGNITE_IMPORT_EXPORT bool operator==(const BigInteger& val1, const BigInteger& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if not equal. + */ + IGNITE_IMPORT_EXPORT bool operator!=(const BigInteger& val1, const BigInteger& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if less. + */ + IGNITE_IMPORT_EXPORT bool operator<(const BigInteger& val1, const BigInteger& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if less or equal. + */ + IGNITE_IMPORT_EXPORT bool operator<=(const BigInteger& val1, const BigInteger& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if gretter. + */ + IGNITE_IMPORT_EXPORT bool operator>(const BigInteger& val1, const BigInteger& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if gretter or equal. + */ + IGNITE_IMPORT_EXPORT bool operator>=(const BigInteger& val1, const BigInteger& val2); + } + } +} + +#endif //_IGNITE_ODBC_COMMON_BIG_INTEGER diff --git a/src/odbc/include/ignite/odbc/common/bits.h b/src/odbc/include/ignite/odbc/common/bits.h new file mode 100644 index 000000000..d53a78e37 --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/bits.h @@ -0,0 +1,221 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _IGNITE_ODBC_COMMON_BITS +#define _IGNITE_ODBC_COMMON_BITS + +#include + +#include +#include + +namespace ignite +{ + namespace odbc + { + namespace common + { + namespace bits + { + /** + * Maximum number of digits in uint64_t number. + */ + const int32_t UINT64_MAX_PRECISION = 20; + + /** + * Get number of trailing zero bits in the two's complement binary + * representation of the specified 32-bit int value. + * + * @param i The value whose bits are to be counted. + * @return The number of trailing zero bits in the two's complement + * binary representation of the specified 32-bit int value. + */ + IGNITE_IMPORT_EXPORT int32_t NumberOfTrailingZerosI32(int32_t i); + + /** + * Get number of leading zero bits in the two's complement binary + * representation of the specified 32-bit int value. + * + * @param i The value whose bits are to be counted. + * @return The number of leading zero bits in the two's complement + * binary representation of the specified 32-bit int value. + */ + IGNITE_IMPORT_EXPORT int32_t NumberOfLeadingZerosI32(int32_t i); + + /** + * Get number of leading zero bits in the two's complement binary + * representation of the specified 32-bit int value. + * + * @param i The value whose bits are to be counted. + * @return The number of leading zero bits in the two's complement + * binary representation of the specified 32-bit int value. + */ + IGNITE_IMPORT_EXPORT int32_t NumberOfLeadingZerosU32(uint32_t i); + + /** + * Get number of leading zero bits in the two's complement binary + * representation of the specified 64-bit int value. + * + * @param i The value whose bits are to be counted. + * @return The number of leading zero bits in the two's complement + * binary representation of the specified 64-bit int value. + */ + IGNITE_IMPORT_EXPORT int32_t NumberOfLeadingZerosI64(int64_t i); + + /** + * Get number of leading zero bits in the two's complement binary + * representation of the specified 64-bit int value. + * + * @param i The value whose bits are to be counted. + * @return The number of leading zero bits in the two's complement + * binary representation of the specified 64-bit int value. + */ + IGNITE_IMPORT_EXPORT int32_t NumberOfLeadingZerosU64(uint64_t i); + + /** + * Get the number of one-bits in the two's complement binary + * representation of the specified 32-bit int value. + * + * @param i The value whose bits are to be counted. + * @return The number of one-bits in the two's complement binary + * representation of the specified 32-bit int value. + */ + IGNITE_IMPORT_EXPORT int32_t BitCountI32(int32_t i); + + /** + * Get bit length for the specified signed 32-bit int value. + * + * @param i The value to get bit length for. + * @return The number of significant bits in the two's complement binary + * representation of the specified 32-bit int value. + */ + IGNITE_IMPORT_EXPORT int32_t BitLengthI32(int32_t i); + + /** + * Get bit length for the specified unsigned 32-bit int value. + * + * @param i The value to get bit length for. + * @return The number of significant bits in the two's complement binary + * representation of the specified 32-bit int value. + */ + IGNITE_IMPORT_EXPORT int32_t BitLengthU32(uint32_t i); + + /** + * Calcutale capasity for required size. + * Rounds up to the nearest power of two. + * + * @param size Needed capasity. + * @return Recomended capasity to allocate. + */ + IGNITE_IMPORT_EXPORT int32_t GetCapasityForSize(int32_t size); + + /** + * Get the number of decimal digits of the integer value. + * + * @param x The value. + * @return The number of decimal digits of the integer value. + */ + IGNITE_IMPORT_EXPORT int32_t DigitLength(uint64_t x); + + /** + * Get n-th power of ten. + * + * @param n Power. Should be in range [0, UINT64_MAX_PRECISION] + * @return 10 pow n, if n is in range [0, UINT64_MAX_PRECISION]. + * Otherwise, behaviour is undefined. + */ + IGNITE_IMPORT_EXPORT uint64_t TenPowerU64(int32_t n); + + /** + * Get the signum function of the specified 64-bit integer value. + * The return value is -1 if the specified value is negative; 0 if the + * specified value is zero; and 1 if the specified value is positive. + * + * @param i the value whose signum is to be computed + * @return The signum function of the specified value. + */ + inline int32_t Signum64(int64_t i) + { + return (static_cast(-i) >> 63) | (i >> 63); + } + + /** + * Makes single 64-bit integer number out of two 32-bit numbers. + * + * @param higher Higher bits part. + * @param lower Lower bits part. + * @return New 64-bit integer. + */ + inline uint64_t MakeU64(uint32_t higher, uint32_t lower) + { + return (static_cast(higher) << 32) | lower; + } + + /** + * Makes single 64-bit integer number out of two 32-bit numbers. + * + * @param higher Higher bits part. + * @param lower Lower bits part. + * @return New 64-bit integer. + */ + inline int64_t MakeI64(uint32_t higher, uint32_t lower) + { + return static_cast(MakeU64(higher, lower)); + } + + /** + * Makes single 32-bit integer number out of two 32-bit numbers, + * shifted by specified number of bits. First number x is shifted + * to the left. + * x y + * [........][........] + * ^[........] + * n res + * + * @param x First part. + * @param y Second part. + * @param n Number of bits to shift. + * @return New 32-bit integer. + */ + inline uint32_t MakeU32(uint32_t x, uint32_t y, int32_t n) + { + return (x << n) | (y >> (32 - n)); + } + + /** + * Makes single 32-bit integer number out of two 32-bit numbers, + * shifted by specified number of bits. First number x is shifted + * to the left. + * x y + * [........][........] + * ^[........] + * n res + * + * @param x First part. + * @param y Second part. + * @param n Number of bits to shift. + * @return New 32-bit integer. + */ + inline int32_t MakeI32(uint32_t x, uint32_t y, int32_t n) + { + return static_cast(MakeU32(x, y, n)); + } + } + } + } +} + +#endif //_IGNITE_ODBC_COMMON_BITS diff --git a/src/odbc/include/ignite/odbc/common/concurrent.h b/src/odbc/include/ignite/odbc/common/concurrent.h new file mode 100644 index 000000000..c0615f22a --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/concurrent.h @@ -0,0 +1,605 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_COMMON_CONCURRENT +#define _IGNITE_ODBC_COMMON_CONCURRENT + +#include +#include + +#include "ignite/odbc/common/concurrent_os.h" + +namespace ignite +{ + namespace odbc + { + namespace common + { + namespace concurrent + { + /** + * Type tag for static pointer cast. + */ + struct StaticTag {}; + + /** + * Default deleter implementation. + * + * @param obj Object to be deleted. + */ + template + IGNITE_IMPORT_EXPORT void SharedPointerDefaultDeleter(T* obj) + { + delete obj; + } + + /** + * Empty deleter implementation. + * + * @param obj Object to be deleted. + */ + template + IGNITE_IMPORT_EXPORT void SharedPointerEmptyDeleter(T*) + { + // No-op. + } + + /** + * Holder of shared pointer data. + */ + class IGNITE_IMPORT_EXPORT SharedPointerImpl + { + public: + typedef void(*DeleterType)(void*); + /** + * Constructor. + * + * @param ptr Raw pointer. + */ + SharedPointerImpl(void* ptr, DeleterType deleter); + + /** + * Get raw pointer. + * + * @return Raw pointer. + */ + void* Pointer(); + + /** + * Get raw pointer. + * + * @return Raw pointer. + */ + const void* Pointer() const; + + /** + * Get raw pointer. + * + * @return Raw pointer. + */ + DeleterType Deleter(); + + /** + * Increment usage counter. + */ + void Increment(); + + /** + * Decrement usage counter. + * + * @return True if counter reached zero. + */ + bool Decrement(); + private: + /** Raw pointer. */ + void* ptr; + + /** Deleter. */ + DeleterType deleter; + + /** Reference count. */ + int32_t refCnt; + + IGNITE_NO_COPY_ASSIGNMENT(SharedPointerImpl); + }; + + /* Forward declaration. */ + template + class IGNITE_IMPORT_EXPORT EnableSharedFromThis; + + /* Forward declaration. */ + template + inline void ImplEnableShared(EnableSharedFromThis* some, SharedPointerImpl* impl); + + // Do nothing if the instance is not derived from EnableSharedFromThis. + inline void ImplEnableShared(const volatile void*, const volatile void*) + { + // No-op. + } + + /** + * Shared pointer. + */ + template + class IGNITE_IMPORT_EXPORT SharedPointer + { + public: + friend class EnableSharedFromThis; + + template + friend class SharedPointer; + + /** + * Constructor. + */ + SharedPointer() : + ptr(0), + impl(0) + { + // No-op. + } + + /** + * Constructor. + * + * @param ptr Raw pointer. + * @param deleter Delete function. + */ + SharedPointer(T* ptr, void(*deleter)(T*) = &SharedPointerDefaultDeleter) : + ptr(ptr), + impl(0) + { + if (ptr) + { + impl = new SharedPointerImpl(ptr, reinterpret_cast(deleter)); + ImplEnableShared(ptr, impl); + } + } + + /** + * Constructor. + * + * @param ptr Raw pointer. + * @param deleter Delete function. + */ + template + SharedPointer(T2* ptr, void(*deleter)(T2*) = &SharedPointerDefaultDeleter) : + ptr(ptr), + impl(0) + { + if (ptr) + { + impl = new SharedPointerImpl(ptr, reinterpret_cast(deleter)); + ImplEnableShared(ptr, impl); + } + } + + /** + * Copy constructor. + * + * @param other Instance to copy. + */ + SharedPointer(const SharedPointer& other) : + ptr(other.ptr), + impl(other.impl) + { + if (impl) + impl->Increment(); + } + + /** + * Copy constructor. + * + * @param other Instance to copy. + */ + template + SharedPointer(const SharedPointer& other) : + ptr(other.ptr), + impl(other.impl) + { + if (impl) + impl->Increment(); + } + + /** + * Static-cast constructor. + * + * @param other Instance to copy. + */ + template + SharedPointer(const SharedPointer& other, StaticTag) : + ptr(static_cast(other.ptr)), + impl(other.impl) + { + if (impl) + impl->Increment(); + } + + /** + * Assignment operator. + * + * @param other Other instance. + */ + SharedPointer& operator=(const SharedPointer& other) + { + if (this != &other) + { + SharedPointer tmp(other); + + Swap(tmp); + } + + return *this; + } + + /** + * Assignment operator. + * + * @param other Other instance. + */ + template + SharedPointer& operator=(const SharedPointer& other) + { + SharedPointer tmp(other); + + Swap(tmp); + + return *this; + } + + /** + * Destructor. + */ + ~SharedPointer() + { + if (impl && impl->Decrement()) + { + void* ptr0 = impl->Pointer(); + + void(*deleter)(void*) = impl->Deleter(); + + deleter(ptr0); + + delete impl; + + ptr = 0; + } + } + + /** + * Get raw pointer. + * + * @return Raw pointer. + */ + T* Get() + { + return ptr; + } + + /** + * Get raw pointer. + * + * @return Raw pointer. + */ + const T* Get() const + { + return ptr; + } + + /** + * Check whether underlying raw pointer is valid. + * + * Invalid instance can be returned if some of the previous + * operations have resulted in a failure. For example invalid + * instance can be returned by not-throwing version of method + * in case of error. Invalid instances also often can be + * created using default constructor. + * + * @return True if valid. + */ + bool IsValid() const + { + return impl != 0; + } + + /** + * Swap pointer content with another instance. + * + * @param other Other instance. + */ + void Swap(SharedPointer& other) + { + if (this != &other) + { + T* ptrTmp = ptr; + SharedPointerImpl* implTmp = impl; + + ptr = other.ptr; + impl = other.impl; + + other.ptr = ptrTmp; + other.impl = implTmp; + } + } + + private: + /* Pointer. */ + T* ptr; + + /** Implementation. */ + SharedPointerImpl* impl; + }; + + /** + * Enables static-cast semantics for SharedPointer. + * + * @param val Value to cast. + */ + template + SharedPointer StaticPointerCast(const SharedPointer& val) + { + return SharedPointer(val, StaticTag()); + } + + /** + * The class provides functionality that allows objects of derived + * classes to create instances of shared_ptr pointing to themselves + * and sharing ownership with existing shared_ptr objects. + */ + template + class IGNITE_IMPORT_EXPORT EnableSharedFromThis + { + public: + /** + * Default constructor. + */ + EnableSharedFromThis() : self(0) + { + // No-op. + } + + /** + * Copy constructor. + */ + EnableSharedFromThis(const EnableSharedFromThis&) : self(0) + { + // No-op. + } + + /** + * Assignment operator. + */ + EnableSharedFromThis& operator=(const EnableSharedFromThis&) + { + return *this; + } + + /** + * Destructor. + */ + virtual ~EnableSharedFromThis() + { + // No-op. + } + + /** + * Create shared pointer for this instance. + * + * Can only be called on already shared object. + * @return New shared pointer instance. + */ + SharedPointer SharedFromThis() + { + assert(self != 0); + + SharedPointer ptr; + + ptr.impl = self; + + self->Increment(); + + return ptr; + } + + private: + template + friend void ImplEnableShared(EnableSharedFromThis*, SharedPointerImpl*); + + /** Shared pointer base. */ + SharedPointerImpl* self; + }; + + // Implementation for instances derived from EnableSharedFromThis. + template + inline void ImplEnableShared(EnableSharedFromThis* some, SharedPointerImpl* impl) + { + if (some) + some->self = impl; + } + + /** + * Lock guard. + */ + template + class LockGuard + { + public: + /** + * Constructor. + * + * @param lock Lockable object. + */ + LockGuard(T& lock) : + lock(&lock) + { + lock.Enter(); + } + + /** + * Destructor. + */ + ~LockGuard() + { + if (lock) + lock->Leave(); + } + + /** + * Releases control over lock without unlocking it. + */ + void Forget() + { + lock = 0; + } + + /** + * Releases control over lock and unlocks it as if it would + * go out of scope. + */ + void Reset() + { + if (lock) + { + lock->Leave(); + + Forget(); + } + } + + private: + T* lock; + }; + + typedef LockGuard CsLockGuard; + + /** + * Shared lock guard. + * Locks guard in shared mode. + */ + template + class SharedLockGuard + { + public: + /** + * Constructor. + * + * @param lock Lockable object. + */ + SharedLockGuard(T& lock) : + lock(&lock) + { + lock.LockShared(); + } + + /** + * Destructor. + */ + ~SharedLockGuard() + { + if (lock) + lock->ReleaseShared(); + } + + /** + * Releases control over lock without unlocking it. + */ + void Forget() + { + lock = 0; + } + + /** + * Releases control over lock and unlocks it as if it would + * go out of scope. + */ + void Reset() + { + if (lock) + { + lock->ReleaseShared(); + + Forget(); + } + } + + private: + T* lock; + }; + + typedef SharedLockGuard RwSharedLockGuard; + + /** + * Exclusive lock guard. + * Locks guard in exclusive mode. + */ + template + class ExclusiveLockGuard + { + public: + /** + * Constructor. + * + * @param lock Lockable object. + */ + ExclusiveLockGuard(T& lock) : + lock(&lock) + { + lock.LockExclusive(); + } + + /** + * Destructor. + */ + ~ExclusiveLockGuard() + { + if (lock) + lock->ReleaseExclusive(); + } + + /** + * Releases control over lock without unlocking it. + */ + void Forget() + { + lock = 0; + } + + /** + * Releases control over lock and unlocks it as if it would + * go out of scope. + */ + void Reset() + { + if (lock) + { + lock->ReleaseExclusive(); + + Forget(); + } + } + + private: + T* lock; + }; + + typedef ExclusiveLockGuard RwExclusiveLockGuard; + } // namespace concurrent + } // namespace common + } // namespace odbc +} // namespace ignite + +#endif //_IGNITE_ODBC_COMMON_CONCURRENT diff --git a/src/odbc/include/ignite/odbc/common/decimal.h b/src/odbc/include/ignite/odbc/common/decimal.h new file mode 100644 index 000000000..9728fc845 --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/decimal.h @@ -0,0 +1,530 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_COMMON_DECIMAL +#define _IGNITE_ODBC_COMMON_DECIMAL + +#include +#include + +#include +#include + +#include + +namespace ignite +{ + namespace odbc + { + namespace common + { + /** + * Big decimal number implementation. + */ + class IGNITE_IMPORT_EXPORT Decimal + { + public: + /** + * Default constructor. + */ + Decimal(); + + /** + * Constructor. + * + * @param mag Bytes of the magnitude. Should be positive, sign is + * passed using separate argument. + * @param len Magnitude length in bytes. + * @param scale Scale. + * @param sign Sign of the decimal. Should be -1 for negative numbers + * and 1 otherwise. + * @param bigEndian If true then magnitude is in big-endian. Otherwise + * the byte order of the magnitude considered to be little-endian. + */ + Decimal(const int8_t* mag, int32_t len, int32_t scale, int32_t sign, bool bigEndian = true); + + /** + * Copy constructor. + * + * @param other Other instance. + */ + Decimal(const Decimal& other); + + /** + * Integer constructor. + * + * @param val Integer value. + */ + explicit Decimal(int64_t val); + + /** + * Integer constructor with scale. + * + * @param val Integer value. + * @param scale Scale. + */ + Decimal(int64_t val, int32_t scale); + + /** + * BigInteger constructor with scale. + * + * @param val BigInteger value. + * @param scale Scale. + */ + Decimal(const common::BigInteger& val, int32_t scale); + + /** + * String constructor. + * + * @param val String to assign. + * @param len String length. + */ + Decimal(const char* val, int32_t len); + + /** + * String constructor. + * + * @param val String to assign. + */ + explicit Decimal(const std::string& val) : + scale(0), + magnitude(0) + { + AssignString(val); + } + + /** + * Destructor. + */ + ~Decimal(); + + /** + * Copy operator. + * + * @param other Other instance. + * @return This. + */ + Decimal& operator=(const Decimal& other); + + /** + * Convert to double. + */ + operator double() const; + + /** + * Convert to int64_t. + */ + operator int64_t() const; + + /** + * Convert to double. + * + * @return Double value. + */ + double ToDouble() const; + + /** + * Convert to int64_t. + * + * @return int64_t value. + */ + int64_t ToInt64() const; + + /** + * Get scale. + * + * @return Scale. + */ + int32_t GetScale() const; + + /** + * Set scale. + * + * @param scale Scale to set. + * @param res Result is placed here. Can be *this. + */ + void SetScale(int32_t scale, Decimal& res) const; + + /** + * Get precision of the Decimal. + * + * @return Number of the decimal digits in the decimal representation + * of the value. + */ + int32_t GetPrecision() const; + + /** + * Get unscaled value. + * + * @return Unscaled value. + */ + const common::BigInteger& GetUnscaledValue() const; + + /** + * Swap function for the Decimal type. + * + * @param other Other instance. + */ + void Swap(Decimal& second); + + /** + * Get length of the magnitude. + * + * @return Length of the magnitude. + */ + int32_t GetMagnitudeLength() const; + + /** + * Assign specified value to this Decimal. + * + * @param val String to assign. + */ + void AssignString(const std::string& val) + { + AssignString(val.data(), static_cast(val.size())); + } + + /** + * Assign specified value to this Decimal. + * + * @param val String to assign. + * @param len String length. + */ + void AssignString(const char* val, int32_t len); + + /** + * Assign specified value to this Decimal. + * + * @param val Value to assign. + */ + void AssignInt64(int64_t val); + + /** + * Assign specified value to this Decimal. + * + * @param val Value to assign. + */ + void AssignDouble(double val); + + /** + * Assign specified value to this Decimal. + * + * @param val Value to assign. + */ + void AssignUint64(uint64_t val); + + /** + * Compare this instance to another. + * + * @param other Another instance. + * @return Comparasion result - 0 if equal, 1 if this is greater, -1 if + * this is less. + */ + int32_t Compare(const Decimal& other) const; + + /** + * Check whether this value is negative. + * + * @return True if this value is negative and false otherwise. + */ + bool IsNegative() const; + + /** + * Check whether this value is zero. + * + * @return True if this value is negative and false otherwise. + */ + bool IsZero() const; + + /** + * Check whether this value is positive. + * + * @return True if this value is positive and false otherwise. + */ + bool IsPositive() const; + + /** + * Output operator. + * + * @param os Output stream. + * @param val Value to output. + * @return Reference to the first param. + */ + friend std::ostream& operator<<(std::ostream& os, const Decimal& val) + { + const common::BigInteger& unscaled = val.GetUnscaledValue(); + + // Zero magnitude case. Scale does not matter. + if (unscaled.GetMagnitude().IsEmpty()) + return os << '0'; + + // Scale is zero or negative. No decimal point here. + if (val.scale <= 0) + { + os << unscaled; + + // Adding zeroes if needed. + for (int32_t i = 0; i < -val.scale; ++i) + os << '0'; + + return os; + } + + // Getting magnitude as a string. + std::stringstream converter; + + converter << unscaled; + + std::string magStr = converter.str(); + + int32_t magLen = static_cast(magStr.size()); + + int32_t magBegin = 0; + + // If value is negative passing minus sign. + if (magStr[magBegin] == '-') + { + os << magStr[magBegin]; + + ++magBegin; + --magLen; + } + + // Finding last non-zero char. There is no sense in trailing zeroes + // beyond the decimal point. + int32_t lastNonZero = static_cast(magStr.size()) - 1; + + while (lastNonZero >= magBegin && magStr[lastNonZero] == '0') + --lastNonZero; + + // This is expected as we already covered zero number case. + assert(lastNonZero >= magBegin); + + int32_t dotPos = magLen - val.scale; + + if (dotPos <= 0) + { + // Means we need to add leading zeroes. + os << '0' << '.'; + + while (dotPos < 0) + { + ++dotPos; + + os << '0'; + } + + os.write(&magStr[magBegin], static_cast(lastNonZero) - magBegin + 1); + } + else + { + // Decimal point is in the middle of the number. + // Just output everything before the decimal point. + os.write(&magStr[magBegin], dotPos); + + int32_t afterDot = lastNonZero - dotPos - magBegin + 1; + + if (afterDot > 0) + { + os << '.'; + + os.write(&magStr[magBegin + dotPos], afterDot); + } + } + + return os; + } + + /** + * Input operator. + * + * @param is Input stream. + * @param val Value to input. + * @return Reference to the first param. + */ + friend std::istream& operator>>(std::istream& is, Decimal& val) + { + std::istream::sentry sentry(is); + + // Return zero if input failed. + val.AssignInt64(0); + + if (!is) + return is; + + // Current char. + int c = is.peek(); + + // Current value parts. + uint64_t part = 0; + int32_t partDigits = 0; + int32_t scale = -1; + int32_t sign = 1; + + common::BigInteger& mag = val.magnitude; + common::BigInteger pow; + common::BigInteger bigPart; + + if (!is) + return is; + + // Checking sign. + if (c == '-' || c == '+') + { + if (c == '-') + sign = -1; + + is.ignore(); + c = is.peek(); + } + + // Reading number itself. + while (is) + { + if (isdigit(c)) + { + part = part * 10 + (c - '0'); + ++partDigits; + } + else if (c == '.' && scale < 0) + { + // We have found decimal point. Starting counting scale. + scale = 0; + } + else + break; + + is.ignore(); + c = is.peek(); + + if (part >= 1000000000000000000U) + { + common::BigInteger::GetPowerOfTen(partDigits, pow); + mag.Multiply(pow, mag); + + mag.Add(part); + + part = 0; + partDigits = 0; + } + + // Counting scale if the decimal point have been encountered. + if (scale >= 0) + ++scale; + } + + // Adding last part of the number. + if (partDigits) + { + common::BigInteger::GetPowerOfTen(partDigits, pow); + + mag.Multiply(pow, mag); + + mag.Add(part); + } + + // Adjusting scale. + if (scale < 0) + scale = 0; + else + --scale; + + // Reading exponent. + if (c == 'e' || c == 'E') + { + is.ignore(); + + int32_t exp = 0; + is >> exp; + + scale -= exp; + } + + val.scale = scale; + + if (sign < 0) + mag.Negate(); + + return is; + } + + private: + /** Scale. */ + int32_t scale; + + /** Magnitude. */ + common::BigInteger magnitude; + }; + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if equal. + */ + IGNITE_IMPORT_EXPORT bool operator==(const Decimal& val1, const Decimal& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if not equal. + */ + IGNITE_IMPORT_EXPORT bool operator!=(const Decimal& val1, const Decimal& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if less. + */ + IGNITE_IMPORT_EXPORT bool operator<(const Decimal& val1, const Decimal& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if less or equal. + */ + IGNITE_IMPORT_EXPORT bool operator<=(const Decimal& val1, const Decimal& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if gretter. + */ + IGNITE_IMPORT_EXPORT bool operator>(const Decimal& val1, const Decimal& val2); + + /** + * Comparison operator. + * + * @param val1 First value. + * @param val2 Second value. + * @return True if gretter or equal. + */ + IGNITE_IMPORT_EXPORT bool operator>=(const Decimal& val1, const Decimal& val2); + } + } +} + +#endif //_IGNITE_ODBC_COMMON_DECIMAL diff --git a/src/odbc/include/ignite/odbc/common/default_allocator.h b/src/odbc/include/ignite/odbc/common/default_allocator.h new file mode 100644 index 000000000..ddf7bdda7 --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/default_allocator.h @@ -0,0 +1,92 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _IGNITE_ODBC_COMMON_DEFAULT_ALLOCATOR +#define _IGNITE_ODBC_COMMON_DEFAULT_ALLOCATOR + +#include +#include + +#include + +namespace ignite +{ + namespace odbc + { + namespace common + { + /** + * Allocator. Manages objects construction and destruction as well + * as a memory allocation. + */ + template + class IGNITE_IMPORT_EXPORT DefaultAllocator + { + public: + typedef T ValueType; + typedef T* PointerType; + typedef T& ReferenceType; + typedef const T* ConstPointerType; + typedef const T& ConstReferenceType; + typedef int32_t SizeType; + typedef int32_t DifferenceType; + + template struct Rebind + { + typedef DefaultAllocator other; + }; + + /** + * Default constructor. + */ + DefaultAllocator() + { + // No-op. + } + + /** + * Destructor. + */ + ~DefaultAllocator() + { + // No-op. + } + + PointerType Allocate(SizeType len, void* = 0) + { + return static_cast(::operator new(len * sizeof(ValueType))); + } + + void Deallocate(PointerType ptr, SizeType) + { + ::operator delete(ptr); + } + + void Construct(PointerType p, ConstReferenceType val) + { + new (p) ValueType(val); + } + + void Destruct(PointerType p) + { + p->~ValueType(); + } + }; + } + } +} + +#endif // _IGNITE_ODBC_COMMON_DEFAULT_ALLOCATOR diff --git a/src/odbc/include/ignite/odbc/common/dynamic_size_array.h b/src/odbc/include/ignite/odbc/common/dynamic_size_array.h new file mode 100644 index 000000000..109ccc51c --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/dynamic_size_array.h @@ -0,0 +1,418 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _IGNITE_ODBC_COMMON_DYNAMIC_SIZE_ARRAY +#define _IGNITE_ODBC_COMMON_DYNAMIC_SIZE_ARRAY + +#include +#include +#include + +#include + +#include +#include +#include + +namespace ignite +{ + namespace odbc + { + namespace common + { + /** + * Dynamic size array is safe container abstraction with a dynamic size. + * This is the analogue of the standard vector. It is needed to be used + * in exported classes as we can't export standard library classes. + */ + template > + class IGNITE_IMPORT_EXPORT DynamicSizeArray + { + public: + typedef T ValueType; + typedef A AllocatorType; + typedef typename AllocatorType::SizeType SizeType; + typedef typename AllocatorType::PointerType PointerType; + typedef typename AllocatorType::ConstPointerType ConstPointerType; + typedef typename AllocatorType::ReferenceType ReferenceType; + typedef typename AllocatorType::ConstReferenceType ConstReferenceType; + + /** + * Default constructor. + * + * Constructs zero-size and zero-capasity array. + */ + DynamicSizeArray(const AllocatorType& allocator = AllocatorType()) : + alloc(allocator), + size(0), + capasity(0), + data(0) + { + // No-op. + } + + /** + * Constructor. + * Constructs empty array with the specified capacity. + * + * @param len Array length. + * @param alloc Allocator. + */ + DynamicSizeArray(SizeType len, const AllocatorType& allocator = AllocatorType()) : + alloc(allocator), + size(0), + capasity(bits::GetCapasityForSize(len)), + data(alloc.Allocate(capasity)) + { + // No-op. + } + + /** + * Raw array constructor. + * + * @param arr Raw array. + * @param len Array length in elements. + */ + DynamicSizeArray(ConstPointerType arr, SizeType len, + const AllocatorType& allocator = AllocatorType()) : + alloc(allocator), + size(0), + capasity(0), + data(0) + { + Assign(arr, len); + } + + /** + * Copy constructor. + * + * @param other Other instance. + */ + DynamicSizeArray(const DynamicSizeArray& other) : + alloc(), + size(0), + capasity(0), + data(0) + { + Assign(other); + } + + /** + * Destructor. + */ + ~DynamicSizeArray() + { + for (PointerType it = data; it != data + size; ++it) + alloc.Destruct(it); + + alloc.Deallocate(data, capasity); + } + + /** + * Assignment operator. + * + * @param other Other instance. + * @return Reference to this instance. + */ + DynamicSizeArray& operator=(const DynamicSizeArray& other) + { + Assign(other); + + return *this; + } + + /** + * Assign new value to the array. + * + * @param other Another array instance. + */ + void Assign(const DynamicSizeArray& other) + { + if (this != &other) + { + alloc = other.alloc; + + Assign(other.GetData(), other.GetSize()); + } + } + + /** + * Assign new value to the array. + * + * @param src Raw array. + * @param len Array length in elements. + */ + void Assign(ConstPointerType src, SizeType len) + { + for (PointerType it = data; it != data + size; ++it) + alloc.Destruct(it); + + if (capasity < len) + { + alloc.Deallocate(data, capasity); + + capasity = bits::GetCapasityForSize(len); + data = alloc.Allocate(capasity); + } + + size = len; + + for (SizeType i = 0; i < size; ++i) + alloc.Construct(data + i, src[i]); + } + + /** + * Append several values to the array. + * + * @param src Raw array. + * @param len Array length in elements. + */ + void Append(ConstPointerType src, SizeType len) + { + Reserve(size + len); + + for (SizeType i = 0; i < len; ++i) + alloc.Construct(data + size + i, src[i]); + + size += len; + } + + /** + * Swap contents of the array with another instance. + * + * @param other Instance to swap with. + */ + void Swap(DynamicSizeArray& other) + { + if (this != &other) + { + std::swap(alloc, other.alloc); + std::swap(size, other.size); + std::swap(capasity, other.capasity); + std::swap(data, other.data); + } + } + + /** + * Get data pointer. + * + * @return Data pointer. + */ + PointerType GetData() + { + return data; + } + + /** + * Get data pointer. + * + * @return Data pointer. + */ + ConstPointerType GetData() const + { + return data; + } + + /** + * Get array size. + * + * @return Array size. + */ + SizeType GetSize() const + { + return size; + } + + /** + * Get capasity. + * + * @return Array capasity. + */ + SizeType GetCapasity() const + { + return capasity; + } + + /** + * Element access operator. + * + * @param idx Element index. + * @return Element reference. + */ + ReferenceType operator[](SizeType idx) + { + assert(idx < size); + + return data[idx]; + } + + /** + * Element access operator. + * + * @param idx Element index. + * @return Element reference. + */ + ConstReferenceType operator[](SizeType idx) const + { + assert(idx < size); + + return data[idx]; + } + + /** + * Check if the array is empty. + * + * @return True if the array is empty. + */ + bool IsEmpty() const + { + return size == 0; + } + + /** + * Clears the array. + */ + void Clear() + { + for (PointerType it = data; it != data + size; ++it) + alloc.Destruct(it); + + size = 0; + } + + /** + * Reserves not less than specified elements number so array is not + * going to grow on append. + * + * @param newCapacity Desired capasity. + */ + void Reserve(SizeType newCapacity) + { + if (capasity < newCapacity) + { + DynamicSizeArray tmp(newCapacity); + + tmp.Assign(*this); + + Swap(tmp); + } + } + + /** + * Resizes array. Destructs elements if the specified size is less + * than the array's size. Default-constructs elements if the + * specified size is more than the array's size. + * + * @param newSize Desired size. + */ + void Resize(SizeType newSize) + { + if (capasity < newSize) + Reserve(newSize); + + if (newSize > size) + { + for (PointerType it = data + size; it < data + newSize; ++it) + alloc.Construct(it, ValueType()); + } + else + { + for (PointerType it = data + newSize; it < data + size; ++it) + alloc.Destruct(it); + } + + size = newSize; + } + + /** + * Get last element. + * + * @return Last element reference. + */ + const ValueType& Back() const + { + assert(size > 0); + + return data[size - 1]; + } + + /** + * Get last element. + * + * @return Last element reference. + */ + ValueType& Back() + { + assert(size > 0); + + return data[size - 1]; + } + + /** + * Get first element. + * + * @return First element reference. + */ + const ValueType& Front() const + { + assert(size > 0); + + return data[0]; + } + + /** + * Get first element. + * + * @return First element reference. + */ + ValueType& Front() + { + assert(size > 0); + + return data[0]; + } + + /** + * Pushes new value to the back of the array, effectively increasing + * array size by one. + * + * @param val Value to push. + */ + void PushBack(ConstReferenceType val) + { + Resize(size + 1); + + Back() = val; + } + + private: + /** Allocator */ + AllocatorType alloc; + + /** Array size. */ + SizeType size; + + /** Array capasity. */ + SizeType capasity; + + /** Data. */ + PointerType data; + }; + } + } +} + +#endif // _IGNITE_ODBC_COMMON_DYNAMIC_SIZE_ARRAY diff --git a/src/odbc/include/ignite/odbc/common/expected.h b/src/odbc/include/ignite/odbc/common/expected.h new file mode 100644 index 000000000..800fda179 --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/expected.h @@ -0,0 +1,303 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_COMMON_EXPECTED +#define _IGNITE_ODBC_COMMON_EXPECTED + +#include + +#include + +namespace ignite +{ + namespace odbc + { + namespace common + { + /** + * Helper class to construct Expected class with error value. + */ + template + struct Unexpected + { + /** Value type. */ + typedef E ValueType; + + /** + * Constructor. + * + * @param e Error value reference. + */ + Unexpected(const ValueType& e) : err(e) + { + // No-op; + } + + /** Error. */ + const ValueType& err; + }; + + /** + * Operation result wrapper. + * + * Represents a type, which can accept one of two value types - expected + * result or error. + * + * @tparam R Result type. + * @tparam E Error type. + * @tparam AR Allocator type used for the Result type. + * @tparam AE Allocator type used for the Error type. + */ + template< + typename R, + typename E, + typename AR = std::allocator, + typename AE = std::allocator > + class Expected + { + public: + /** Result type. */ + typedef R ResultType; + + /** Error type. */ + typedef E ErrorType; + + /** Allocator type used for the ResultType. */ + typedef AR ResultAllocatorType; + + /** Allocator type used for the ErrorType. */ + typedef AE ErrorAllocatorType; + + /** + * Constructor. + * + * Creates new instance, containing expected value. + * @param res Result. + */ + Expected(const ResultType& res) : + ok(true) + { + ResultAllocatorType ral; + + ral.construct(AsResult(), res); + } + + /** + * Constructor. + * + * Creates new instance, containing error. + * @param err Result. + */ + explicit Expected(Unexpected err) : + ok(false) + { + ErrorAllocatorType ral; + + ral.construct(AsError(), err.err); + } + + /** + * Copy constructor. + * + * @param other Other. + */ + Expected(const Expected& other) : + ok(other.ok) + { + if (ok) + { + ResultAllocatorType ral; + + ral.construct(AsResult(), *other.AsResult()); + } + else + { + ErrorAllocatorType ral; + + ral.construct(AsError(), *other.AsError()); + } + } + + /** + * Destructor. + */ + ~Expected() + { + if (ok) + { + ResultAllocatorType ral; + + ral.destroy(AsResult()); + } + else + { + ErrorAllocatorType ral; + + ral.destroy(AsError()); + } + } + + /** + * Check if the value is OK. + * + * @return @c false if the value is an error and @c true otherwise. + */ + bool IsOk() const + { + return ok; + } + + /** + * Get result. Constant accesser. + * + * @return Result if it was set before. + * @throw ErrorType if there is no result. + */ + const ResultType& GetResult() const + { + if (!ok) + throw *AsError(); + + return *AsResult(); + } + + /** + * Get result. + * + * @return Result if it was set before. + * @throw ErrorType if there is no result. + */ + ResultType& GetResult() + { + if (!ok) + throw *AsError(); + + return *AsResult(); + } + + /** + * Get result. Constant accesser. + * + * @return Result if it was set before. + * @throw ErrorType if there is no result. + */ + const ResultType& operator*() const + { + return GetResult(); + } + + /** + * Get result. + * + * @return Result if it was set before. + * @throw ErrorType if there is no result. + */ + ResultType& operator*() + { + return GetResult(); + } + + /** + * Get result. Constant accesser. + * + * @return Result if it was set before. + * @throw ErrorType if there is no result. + */ + const ResultType& operator->() const + { + return GetResult(); + } + + /** + * Get result. + * + * @return Result if it was set before. + * @throw ErrorType if there is no result. + */ + ResultType& operator->() + { + return GetResult(); + } + + /** + * Get error. + * + * @return Error if it was set before. If there is no error, default + * constructed error is returned (which is expected to be "No error"). + */ + const ErrorType& GetError() const + { + static ErrorType noError; + + if (ok) + return noError; + + return *AsError(); + } + + private: + /** + * Get storage as an result. + * + * @return Storage pointer as an result pointer. + */ + ResultType* AsResult() + { + return reinterpret_cast(&storage); + } + + /** + * Get storage as an result. + * + * @return Storage pointer as an result pointer. + */ + const ResultType* AsResult() const + { + return reinterpret_cast(&storage); + } + + /** + * Get storage as an error. + * + * @return Storage pointer as an error pointer. + */ + ErrorType* AsError() + { + return reinterpret_cast(&storage); + } + + /** + * Get storage as an error. + * + * @return Storage pointer as an error pointer. + */ + const ErrorType* AsError() const + { + return reinterpret_cast(&storage); + } + + /** Storage. */ + int8_t storage[sizeof(typename Bigger::type)]; + + /** Result flag. Set to @c false if the value is an error. */ + bool ok; + }; + } + } +} + +#endif // _IGNITE_ODBC_COMMON_EXPECTED \ No newline at end of file diff --git a/src/odbc/include/ignite/odbc/common/fixed_size_array.h b/src/odbc/include/ignite/odbc/common/fixed_size_array.h new file mode 100644 index 000000000..a18a60a84 --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/fixed_size_array.h @@ -0,0 +1,262 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _IGNITE_ODBC_COMMON_FIXED_SIZE_ARRAY +#define _IGNITE_ODBC_COMMON_FIXED_SIZE_ARRAY + +#include +#include +#include + +#include +#include + +#include + +namespace ignite +{ + namespace odbc { + namespace common { + /** + * Fixed size array is safe array abstraction with a fixed size. + * The size can be set during runtime though once array is created + * its size can not be changed without resetting arrays content. + */ + template < typename T > + class IGNITE_IMPORT_EXPORT FixedSizeArray { + public: + typedef int32_t SizeType; + + /** + * Default constructor. + * + * Constructs zero-size array. + */ + FixedSizeArray() : size(0), data(0) { + // No-op. + } + + /** + * Constructor. + * Constructs default-initialized array of the specified length. + * Array zeroed if T is a POD type. + * + * @param len Array length. + */ + FixedSizeArray(SizeType len) + : size(len), + // Brackets are here for a purpose - this way allocated + // array is zeroed if T is POD type. + data(new T[size]()) { + // No-op. + } + + /** + * Copy constructor. + * + * @param other Other instance. + */ + FixedSizeArray(const FixedSizeArray< T >& other) + : size(other.size), data(new T[size]) { + Assign(other); + } + + /** + * Raw array constructor. + * + * @param arr Raw array. + * @param len Array length in elements. + */ + FixedSizeArray(const T* arr, SizeType len) : size(len), data(new T[size]) { + Assign(arr, len); + } + + /** + * Assignment operator. + * + * @param other Other instance. + * @return Reference to this instance. + */ + FixedSizeArray< T >& operator=(const FixedSizeArray< T >& other) { + Assign(other); + + return *this; + } + + /** + * Assign new value to the array. + * + * @param other Another array instance. + */ + void Assign(const FixedSizeArray< T >& other) { + if (this != &other) + Assign(other.GetData(), other.GetSize()); + } + + /** + * Assign new value to the array. + * + * @param src Raw array. + * @param len Array length in elements. + */ + void Assign(const T* src, SizeType len) { + // In case we would not need to clean anything + // its okay to call delete[] on 0. + T* toClean = 0; + + if (len != size) { + // Do not clean just yet in case the part of the + // array is being assigned to the array. + toClean = data; + + size = len; + data = new T[size]; + } + + for (SizeType i = 0; i < len; ++i) + data[i] = src[i]; + + delete[] toClean; + } + + /** + * Swap contents of the array with another instance. + * + * @param other Instance to swap with. + */ + void Swap(FixedSizeArray< T >& other) { + if (this != &other) { + std::swap(size, other.size); + std::swap(data, other.data); + } + } + + /** + * Destructor. + */ + ~FixedSizeArray() { + // Not a bug. Delete works just fine on null pointers. + delete[] data; + } + + /** + * Get data pointer. + * + * @return Data pointer. + */ + T* GetData() { + return data; + } + + /** + * Get data pointer. + * + * @return Data pointer. + */ + const T* GetData() const { + return data; + } + + /** + * Get array size. + * + * @return Array size. + */ + SizeType GetSize() const { + return size; + } + + /** + * Copy part of the array and place in another array. + * Contents of the provided array gets swapped with the copy of the + * specified array part. + * + * @param pos Start position. + * @param n Number of elements to copy. + * @param result Instance of an array where result should be placed. + */ + void CopyPart(SizeType pos, SizeType n, FixedSizeArray< T >& result) const { + assert(pos < size); + assert(pos + n <= size); + + result.Assign(data + pos, n); + } + + /** + * Element access operator. + * + * @param idx Element index. + * @return Element reference. + */ + T& operator[](SizeType idx) { + assert(idx < size); + + return data[idx]; + } + + /** + * Element access operator. + * + * @param idx Element index. + * @return Element reference. + */ + const T& operator[](SizeType idx) const { + assert(idx < size); + + return data[idx]; + } + + /** + * Check if the array is empty. + * + * @return True if the array is empty. + */ + bool IsEmpty() const { + return size == 0; + } + + /** + * Resets the state of the array setting it to the specified size + * and erasing its content. + * + * @param newSize New array size. + */ + void Reset(SizeType newSize = 0) { + if (size != newSize) { + delete[] data; + + if (newSize) + data = new T[newSize](); + else + data = 0; + + size = newSize; + } else + std::fill(data, data + size, T()); + } + + private: + /** Array size. */ + SizeType size; + + /** Target array. */ + T* data; + }; + } // namespace common + } // namespace odbc +} + +#endif // _IGNITE_ODBC_COMMON_FIXED_SIZE_ARRAY diff --git a/src/odbc/include/ignite/odbc/common/platform_utils.h b/src/odbc/include/ignite/odbc/common/platform_utils.h new file mode 100644 index 000000000..5e430de2c --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/platform_utils.h @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _IGNITE_ODBC_COMMON_PLATFORM_UTILS +#define _IGNITE_ODBC_COMMON_PLATFORM_UTILS + +#include +#include "ignite/odbc/common/common.h" + +namespace ignite +{ + namespace odbc + { + namespace common + { + typedef std::basic_ostream > StdCharOutStream; + + /** + * Convert struct tm to time_t (UTC). + * + * @param time Standard C type struct tm value. + * @return Standard C type time_t value. + */ + IGNITE_IMPORT_EXPORT time_t IgniteTimeGm(const tm& time); + + /** + * Convert struct tm to time_t (Local time). + * + * @param time Standard C type struct tm value. + * @return Standard C type time_t value. + */ + IGNITE_IMPORT_EXPORT time_t IgniteTimeLocal(const tm& time); + + /** + * Convert time_t to struct tm (UTC). + * + * @param in Standard C type time_t value. + * @param out Standard C type struct tm value. + * @return True on success. + */ + IGNITE_IMPORT_EXPORT bool IgniteGmTime(time_t in, tm& out); + + /** + * Convert time_t to struct tm (Local time). + * + * @param in Standard C type time_t value. + * @param out Standard C type struct tm value. + * @return True on success. + */ + IGNITE_IMPORT_EXPORT bool IgniteLocalTime(time_t in, tm& out); + + /** + * Read system environment variable taking thread-safety in count. + * + * @param name Environment variable name. + * @return Environment variable value if found and empty string otherwise. + */ + IGNITE_IMPORT_EXPORT std::string GetEnv(const std::string& name); + + /** + * Read system environment variable taking thread-safety in count. + * + * @param name Environment variable name. + * @param dflt Default value to return on fail. + * @return Environment variable value if found and @c dflt otherwise. + */ + IGNITE_IMPORT_EXPORT std::string GetEnv(const std::string& name, const std::string& dflt); + + /** + * Ensure that file on the given path exists in the system. + * + * @param path Path. + * @return True if file exists, false otherwise. + */ + IGNITE_IMPORT_EXPORT bool FileExists(const std::string& path); + + /** + * Check if the provided path is the valid directory. + * @return @c true if the provided path is the valid directory. + */ + IGNITE_IMPORT_EXPORT bool IsValidDirectory(const std::string& path); + + /** + * Deletes provided filesystem element if exists. + * @return @c true if the provided path exists. + */ + IGNITE_IMPORT_EXPORT bool DeletePath(const std::string& path); + + /** + * Write file separator to a stream. + * @param ostr Stream. + * @return The same stream for chaining. + */ + IGNITE_IMPORT_EXPORT StdCharOutStream& Fs(StdCharOutStream& ostr); + + /** + * Write dynamic library expansion to a stream. + * @param ostr Stream. + * @return The same stream for chaining. + */ + IGNITE_IMPORT_EXPORT StdCharOutStream& Dle(StdCharOutStream& ostr); + + /** + * Get random seed. + * + * @return Random seed. + */ + IGNITE_IMPORT_EXPORT unsigned GetRandSeed(); + } + } +} + +#endif //_IGNITE_ODBC_COMMON_PLATFORM_UTILS diff --git a/src/odbc/include/ignite/odbc/common/utils.h b/src/odbc/include/ignite/odbc/common/utils.h new file mode 100644 index 000000000..accb2fa84 --- /dev/null +++ b/src/odbc/include/ignite/odbc/common/utils.h @@ -0,0 +1,664 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _IGNITE_ODBC_COMMON_UTILS +#define _IGNITE_ODBC_COMMON_UTILS + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include "ignite/time.h" + +#ifdef IGNITE_FRIEND +# define IGNITE_FRIEND_EXPORT IGNITE_EXPORT +#else +# define IGNITE_FRIEND_EXPORT +#endif + +namespace ignite +{ + namespace odbc + { + namespace common + { + /** + * Replace all alphabetic symbols of the string with their lowercase + * versions. + * @param str String to be transformed. + */ + inline void IntoLower(std::string& str) + { + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + } + + /** + * Get lowercase version of the string. + * + * @param str Input string. + * @return Lowercased version of the string. + */ + inline std::string ToLower(const std::string& str) + { + std::string res(str); + IntoLower(res); + return res; + } + + /** + * Strips leading and trailing whitespaces from string. + * + * @param str String to be transformed. + */ + IGNITE_IMPORT_EXPORT void StripSurroundingWhitespaces(std::string& str); + + /** + * Skip leading spaces. + * + * @param begin Iterator to the beginning of the character sequence. + * @param end Iterator to the end of the character sequence. + * @return Iterator to first non-blanc character. + */ + template + Iterator SkipLeadingSpaces(Iterator begin, Iterator end) + { + Iterator res = begin; + + while (isspace(*res) && res != end) + ++res; + + return res; + } + + /** + * Skip trailing spaces. + * + * @param begin Iterator to the beginning of the character sequence. + * @param end Iterator to the end of the character sequence. + * @return Iterator to last non-blanc character. + */ + template + Iterator SkipTrailingSpaces(Iterator begin, Iterator end) + { + Iterator res = end - 1; + + while (isspace(*res) && res != begin - 1) + --res; + + return res + 1; + } + + /** + * Remove leading and trailing spaces. + * + * @param begin Iterator to the beginning of the character sequence. + * @param end Iterator to the end of the character sequence. + * @return String without leading and trailing spaces. + */ + template + std::string StripSurroundingWhitespaces(Iterator begin, Iterator end) + { + std::string res; + + if (begin >= end) + return res; + + Iterator skipped_leading = SkipLeadingSpaces(begin, end); + Iterator skipped_trailing = SkipTrailingSpaces(skipped_leading, end); + + res.reserve(skipped_trailing - skipped_leading); + + std::copy(skipped_leading, skipped_trailing, std::back_inserter(res)); + + return res; + } + + /** + * Get string representation of long in decimal form. + * + * @param val Long value to be converted to string. + * @return String contataining decimal representation of the value. + */ + inline std::string LongToString(long val) + { + std::stringstream tmp; + tmp << val; + return tmp.str(); + } + + /** + * Parse string to try and get int value. + * + * @param str String to be parsed. + * @return String contataining decimal representation of the value. + */ + inline int ParseInt(const std::string& str) + { + return atoi(str.c_str()); + } + + /** + * Copy characters. + * + * @param val Value. + * @return Result. + */ + IGNITE_IMPORT_EXPORT char* CopyChars(const char* val); + + /** + * Release characters. + * + * @param val Value. + */ + IGNITE_IMPORT_EXPORT void ReleaseChars(char* val); + + /** + * Casts value of one type to another type, using stringstream. + * + * @param val Input value. + * @param res Resulted value. + */ + template + void LexicalCast(const T2& val, T1& res) + { + std::stringstream converter; + + converter << val; + converter >> res; + } + + /** + * Casts value of one type to another type, using stringstream. + * + * @param val Input value. + * @return Resulted value. + */ + template + T1 LexicalCast(const T2& val) + { + T1 res; + + LexicalCast(val, res); + + return res; + } + + /** + * Check if all characters are digits. + * + * @param val Value to check. + */ + IGNITE_IMPORT_EXPORT bool AllDigits(const std::string& val); + + /** + * Converts 32-bit integer to big endian format + * + * @param value Input value + * @return Resulting value + */ + IGNITE_IMPORT_EXPORT uint32_t ToBigEndian(uint32_t value); + + /** + * Convert Date type to standard C type time_t. + * + * @param date Date type value. + * @return Corresponding value of time_t. + */ + inline time_t DateToCTime(const Date& date) + { + return static_cast(date.GetSeconds()); + } + + /** + * Convert Timestamp type to standard C type time_t. + * + * @param ts Timestamp type value. + * @return Corresponding value of time_t. + */ + inline time_t TimestampToCTime(const Timestamp& ts) + { + return static_cast(ts.GetSeconds()); + } + + /** + * Convert Time type to standard C type time_t. + * + * @param time Time type value. + * @return Corresponding value of time_t. + */ + inline time_t TimeToCTime(const Time& time) + { + return static_cast(time.GetSeconds()); + } + + /** + * Convert Date type to standard C type time_t. + * + * @param date Date type value. + * @param ctime Corresponding value of struct tm. + * @return True on success. + */ + inline bool DateToCTm(const Date& date, tm& ctime) + { + time_t tmt = DateToCTime(date); + + return common::IgniteGmTime(tmt, ctime); + } + + /** + * Convert Timestamp type to standard C type struct tm. + * + * @param ts Timestamp type value. + * @param ctime Corresponding value of struct tm. + * @return True on success. + */ + inline bool TimestampToCTm(const Timestamp& ts, tm& ctime) + { + time_t tmt = TimestampToCTime(ts); + + return common::IgniteGmTime(tmt, ctime); + } + + /** + * Convert Time type to standard C type struct tm. + * + * @param time Time type value. + * @param ctime Corresponding value of struct tm. + * @return True on success. + */ + inline bool TimeToCTm(const Time& time, tm& ctime) + { + time_t tmt = TimeToCTime(time); + + return common::IgniteGmTime(tmt, ctime); + } + + /** + * Convert standard C type time_t to Date. + * + * @param ctime Standard C type time_t. + * @return Corresponding value of Date. + */ + inline Date CTimeToDate(time_t ctime) + { + return Date(ctime * 1000); + } + + /** + * Convert standard C type time_t to Time. + * + * @param ctime Standard C type time_t. + * @return Corresponding value of Time. + */ + inline Time CTimeToTime(time_t ctime) + { + return Time(ctime * 1000); + } + + /** + * Convert standard C type time_t to Timestamp type. + * + * @param ctime Standard C type time_t. + * @param ns Nanoseconds second fraction. + * @return Corresponding value of Timestamp. + */ + inline Timestamp CTimeToTimestamp(time_t ctime, int32_t ns) + { + return Timestamp(ctime, ns); + } + + /** + * Convert standard C type struct tm to Date type. + * + * @param ctime Standard C type struct tm. + * @return Corresponding value of Date. + */ + inline Date CTmToDate(const tm& ctime) + { + time_t time = common::IgniteTimeGm(ctime); + + return CTimeToDate(time); + } + + /** + * Convert standard C type struct tm to Time type. + * + * @param ctime Standard C type struct tm. + * @return Corresponding value of Time. + */ + inline Time CTmToTime(const tm& ctime) + { + time_t time = common::IgniteTimeGm(ctime); + + return CTimeToTime(time); + } + + /** + * Convert standard C type struct tm to Timestamp type. + * + * @param ctime Standard C type struct tm. + * @param ns Nanoseconds second fraction. + * @return Corresponding value of Timestamp. + */ + inline Timestamp CTmToTimestamp(const tm& ctime, int32_t ns) + { + time_t time = common::IgniteTimeGm(ctime); + + return CTimeToTimestamp(time, ns); + } + + /** + * Make Date in human understandable way. + * + * Created Date uses GMT timezone. + * + * @param year Year. + * @param month Month. + * @param day Day. + * @param hour Hour. + * @param min Min. + * @param sec Sec. + * @return Date. + */ + IGNITE_FRIEND_EXPORT Date MakeDateGmt(int year = 1900, int month = 1, + int day = 1, int hour = 0, int min = 0, int sec = 0); + + /** + * Make Date in human understandable way. + * + * Created Date uses local timezone. + * + * @param year Year. + * @param month Month. + * @param day Day. + * @param hour Hour. + * @param min Min. + * @param sec Sec. + * @return Date. + */ + IGNITE_FRIEND_EXPORT Date MakeDateLocal(int year = 1900, int month = 1, + int day = 1, int hour = 0, int min = 0, int sec = 0); + + /** + * Make Time in human understandable way. + * + * Created Time uses GMT timezone. + * + * @param hour Hour. + * @param min Minute. + * @param sec Second. + * @return Time. + */ + IGNITE_FRIEND_EXPORT Time MakeTimeGmt(int hour = 0, int min = 0, int sec = 0); + + /** + * Make Time in human understandable way. + * + * Created Time uses Local timezone. + * + * @param hour Hour. + * @param min Minute. + * @param sec Second. + * @return Time. + */ + IGNITE_FRIEND_EXPORT Time MakeTimeLocal(int hour = 0, int min = 0, int sec = 0); + + /** + * Make Timestamp in human understandable way. + * + * Created Timestamp uses GMT timezone. + * + * @param year Year. + * @param month Month. + * @param day Day. + * @param hour Hour. + * @param min Minute. + * @param sec Second. + * @param ns Nanosecond. + * @return Timestamp. + */ + IGNITE_FRIEND_EXPORT Timestamp MakeTimestampGmt(int year = 1900, int month = 1, + int day = 1, int hour = 0, int min = 0, int sec = 0, long ns = 0); + + /** + * Make Date in human understandable way. + * + * Created Timestamp uses Local timezone. + * + * @param year Year. + * @param month Month. + * @param day Day. + * @param hour Hour. + * @param min Minute. + * @param sec Second. + * @param ns Nanosecond. + * @return Timestamp. + */ + IGNITE_FRIEND_EXPORT Timestamp MakeTimestampLocal(int year = 1900, int month = 1, + int day = 1, int hour = 0, int min = 0, int sec = 0, long ns = 0); + + /** + * Meta-programming class. + * Defines T1 as ::type if the condition is true, otherwise + * defines T2 as ::type. + */ + template + struct Conditional + { + typedef T1 type; + }; + + /** + * Specialization for the false case. + */ + template + struct Conditional + { + typedef T2 type; + }; + + /** + * Returns the bigger type. + */ + template + struct Bigger + { + typedef typename Conditional<(sizeof(T1) > sizeof(T2)), T1, T2>::type type; + }; + + /** + * Utility class to bind class instance with member function. + */ + template + class BoundInstance + { + public: + typedef R FunctionReturnType; + typedef T ClassType; + typedef FunctionReturnType(ClassType::* MemberFunctionType)(); + + /** + * Constructor. + * + * @param instance Class instance. + * @param mfunc Member function. + */ + BoundInstance(ClassType* instance, MemberFunctionType mfunc) : + instance(instance), + mfunc(mfunc) + { + // No-op. + } + + /** + * Invoke operator. + * + * @return Result of the invokation of the member function on the bound instance. + */ + FunctionReturnType operator()() + { + return (instance->*mfunc)(); + } + + private: + /** Instance reference. */ + ClassType* instance; + + /** Member function pointer. */ + MemberFunctionType mfunc; + }; + + /** + * Utility function for binding. + */ + template + BoundInstance Bind(T* instance, R(T::* mfunc)()) + { + return BoundInstance(instance, mfunc); + } + + /** + * Method guard class template. + * + * Upon destruction calls provided method on provided class instance. + * + * @tparam T Value type. + */ + template + class MethodGuard + { + public: + /** Value type. */ + typedef T ValueType; + + /** Mehtod type. */ + typedef void (ValueType::*MethodType)(); + + /** + * Constructor. + * + * @param val Instance, to call method on. + * @param method Method to call. + */ + MethodGuard(ValueType* val, MethodType method) : + val(val), + method(method) + { + // No-op. + } + + /** + * Destructor. + */ + ~MethodGuard() + { + if (val && method) + (val->*method)(); + } + + /** + * Release control over object. + */ + void Release() + { + val = 0; + method = 0; + } + + private: + /** Instance, to call method on. */ + ValueType* val; + + /** Method to call. */ + MethodType method; + }; + + /** + * Deinit guard class template. + * + * Upon destruction calls provided deinit function on provided instance. + * + * @tparam T Value type. + */ + template + class DeinitGuard + { + public: + /** Value type. */ + typedef T ValueType; + + /** Deinit function type. */ + typedef void (*FuncType)(ValueType*); + + /** + * Constructor. + * + * @param val Instance, to call method on. + * @param method Method to call. + */ + DeinitGuard(ValueType* val, FuncType method) : + val(val), + func(method) + { + // No-op. + } + + /** + * Destructor. + */ + ~DeinitGuard() + { + if (val && func) + (func)(val); + } + + /** + * Release control over object. + */ + void Release() + { + val = 0; + func = 0; + } + + private: + /** Instance, to call method on. */ + ValueType* val; + + /** Method to call. */ + FuncType func; + }; + + /** + * Get dynamic library full name. + * @param name Name without extension. + * @return Full name. + */ + IGNITE_IMPORT_EXPORT std::string GetDynamicLibraryName(const char* name); + } + } +} + +#endif //_IGNITE_ODBC_COMMON_UTILS diff --git a/src/odbc/include/ignite/odbc/connection.h b/src/odbc/include/ignite/odbc/connection.h index 3fefc8e33..0a917a50d 100644 --- a/src/odbc/include/ignite/odbc/connection.h +++ b/src/odbc/include/ignite/odbc/connection.h @@ -30,7 +30,7 @@ #include "ignite/odbc/diagnostic/diagnosable_adapter.h" #include "ignite/odbc/streaming/streaming_context.h" #include "ignite/odbc/odbc_error.h" -#include "ignite/odbc/end_point.h" +#include "ignite/odbc/jni/java.h" namespace ignite { @@ -228,8 +228,6 @@ namespace ignite if (!success) return false; - parser.Decode(rsp, tempBuffer); - return true; } @@ -489,7 +487,23 @@ namespace ignite * @throw IgniteError on failure. * @return @c true on success and @c false otherwise. */ - bool TryRestoreConnection(); + bool TryRestoreConnection(IgniteError& err); + + /** + * Formats the JDBC connection string from configuration values. + * @return the JDBC connection string. + */ + std::string FormatJdbcConnectionString() const; + + /** + * Creates JVM options + */ + void SetJvmOptions(const std::string& cp); + + /** + * De-initializes the JVM options + */ + void Deinit(); /** * Collect all addresses from config. @@ -515,9 +529,6 @@ namespace ignite /** Parent. */ Environment* env; - /** Client Socket. */ - std::auto_ptr socket; - /** Connection timeout in seconds. */ int32_t timeout; @@ -536,6 +547,12 @@ namespace ignite /** Connection info. */ config::ConnectionInfo info; + /** Java connection object */ + jobject connection; + + /** JVM options */ + std::vector< char* > opts; + /** Streaming context. */ streaming::StreamingContext streamingContext; }; diff --git a/src/odbc/include/ignite/odbc/ignite_error.h b/src/odbc/include/ignite/odbc/ignite_error.h new file mode 100644 index 000000000..5034a6e9c --- /dev/null +++ b/src/odbc/include/ignite/odbc/ignite_error.h @@ -0,0 +1,316 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Declares ignite::IgniteError class. + */ + +#ifndef _IGNITE_ODBC_IGNITE_ERROR +#define _IGNITE_ODBC_IGNITE_ERROR + +#include + +#include +#include + +#include + +#define IGNITE_ERROR_1(code, part1) { \ + std::stringstream stream; \ + stream << (part1); \ + throw ignite::IgniteError(code, stream.str().c_str()); \ +} + +#define IGNITE_ERROR_2(code, part1, part2) { \ + std::stringstream stream; \ + stream << (part1) << (part2); \ + throw ignite::IgniteError(code, stream.str().c_str()); \ +} + +#define IGNITE_ERROR_3(code, part1, part2, part3) { \ + std::stringstream stream; \ + stream << (part1) << (part2) << (part3); \ + throw ignite::IgniteError(code, stream.str().c_str()); \ +} + +#define IGNITE_ERROR_FORMATTED_1(code, msg, key1, val1) { \ + std::stringstream stream; \ + stream << msg << " [" << key1 << "=" << (val1) << "]"; \ + throw ignite::IgniteError(code, stream.str().c_str()); \ +} + +#define IGNITE_ERROR_FORMATTED_2(code, msg, key1, val1, key2, val2) { \ + std::stringstream stream; \ + stream << msg << " [" << key1 << "=" << (val1) << ", " << key2 << "=" << (val2) << "]"; \ + throw ignite::IgniteError(code, stream.str().c_str()); \ +} + +#define IGNITE_ERROR_FORMATTED_3(code, msg, key1, val1, key2, val2, key3, val3) { \ + std::stringstream stream; \ + stream << msg << " [" << key1 << "=" << (val1) << ", " << key2 << "=" << (val2) << ", " << key3 << "=" << (val3) << "]"; \ + throw ignite::IgniteError(code, stream.str().c_str()); \ +} + +#define IGNITE_ERROR_FORMATTED_4(code, msg, key1, val1, key2, val2, key3, val3, key4, val4) { \ + std::stringstream stream; \ + stream << msg << " [" << key1 << "=" << (val1) << ", " << key2 << "=" << (val2) << ", " << key3 << "=" << (val3) << ", " << key4 << "=" << (val4) << "]"; \ + throw ignite::IgniteError(code, stream.str().c_str()); \ +} + +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4275) +#endif //_MSC_VER + +namespace ignite +{ + namespace odbc + { + namespace java + { + /* JNI error constants. */ + const int IGNITE_JNI_ERR_SUCCESS = 0; + const int IGNITE_JNI_ERR_GENERIC = 1; + const int IGNITE_JNI_ERR_JVM_INIT = 2; + const int IGNITE_JNI_ERR_JVM_ATTACH = 3; + } + + /** + * %Ignite error information. + */ + class IGNITE_IMPORT_EXPORT IgniteError : public std::exception + { + public: + /** Success. */ + static const int IGNITE_SUCCESS = 0; + + /** Failed to initialize JVM. */ + static const int IGNITE_ERR_JVM_INIT = 1; + + /** Failed to attach to JVM. */ + static const int IGNITE_ERR_JVM_ATTACH = 2; + + /** JVM library is not found. */ + static const int IGNITE_ERR_JVM_LIB_NOT_FOUND = 3; + + /** Failed to load JVM library. */ + static const int IGNITE_ERR_JVM_LIB_LOAD_FAILED = 4; + + /** JVM classpath is not provided. */ + static const int IGNITE_ERR_JVM_NO_CLASSPATH = 5; + + /** JVM error: no class definition found. */ + static const int IGNITE_ERR_JVM_NO_CLASS_DEF_FOUND = 6; + + /** JVM error: no such method. */ + static const int IGNITE_ERR_JVM_NO_SUCH_METHOD = 7; + + /** Memory operation error. */ + static const int IGNITE_ERR_MEMORY = 1001; + + /** Binary error. */ + static const int IGNITE_ERR_BINARY = 1002; + + /** Standard library exception. */ + static const int IGNITE_ERR_STD = 1003; + + /** Generic %Ignite error. */ + static const int IGNITE_ERR_GENERIC = 2000; + + /** Illegal argument passed. */ + static const int IGNITE_ERR_ILLEGAL_ARGUMENT = 2001; + + /** Illegal state. */ + static const int IGNITE_ERR_ILLEGAL_STATE = 2002; + + /** Unsupported operation. */ + static const int IGNITE_ERR_UNSUPPORTED_OPERATION = 2003; + + /** Thread has been interrup. */ + static const int IGNITE_ERR_INTERRUPTED = 2004; + + /** Cluster group is empty. */ + static const int IGNITE_ERR_CLUSTER_GROUP_EMPTY = 2005; + + /** Cluster topology problem. */ + static const int IGNITE_ERR_CLUSTER_TOPOLOGY = 2006; + + /** Compute execution rejected. */ + static const int IGNITE_ERR_COMPUTE_EXECUTION_REJECTED = 2007; + + /** Compute job failover. */ + static const int IGNITE_ERR_COMPUTE_JOB_FAILOVER = 2008; + + /** Compute task cancelled. */ + static const int IGNITE_ERR_COMPUTE_TASK_CANCELLED = 2009; + + /** Compute task timeout. */ + static const int IGNITE_ERR_COMPUTE_TASK_TIMEOUT = 2010; + + /** Compute user undeclared exception. */ + static const int IGNITE_ERR_COMPUTE_USER_UNDECLARED_EXCEPTION = 2011; + + /** Generic cache error. */ + static const int IGNITE_ERR_CACHE = 2012; + + /** Generic cache loader error. */ + static const int IGNITE_ERR_CACHE_LOADER = 2013; + + /** Generic cache writer error. */ + static const int IGNITE_ERR_CACHE_WRITER = 2014; + + /** Generic cache entry processor error. */ + static const int IGNITE_ERR_ENTRY_PROCESSOR = 2015; + + /** Cache atomic update timeout. */ + static const int IGNITE_ERR_CACHE_ATOMIC_UPDATE_TIMEOUT = 2016; + + /** Cache partial update. */ + static const int IGNITE_ERR_CACHE_PARTIAL_UPDATE = 2017; + + /** Transaction optimisitc exception. */ + static const int IGNITE_ERR_TX_OPTIMISTIC = 2018; + + /** Transaction timeout. */ + static const int IGNITE_ERR_TX_TIMEOUT = 2019; + + /** Transaction rollback. */ + static const int IGNITE_ERR_TX_ROLLBACK = 2020; + + /** Transaction heuristic exception. */ + static const int IGNITE_ERR_TX_HEURISTIC = 2021; + + /** Authentication error. */ + static const int IGNITE_ERR_AUTHENTICATION = 2022; + + /** Security error. */ + static const int IGNITE_ERR_SECURITY = 2023; + + /** Future state error. */ + static const int IGNITE_ERR_FUTURE_STATE = 2024; + + /** Networking error. */ + static const int IGNITE_ERR_NETWORK_FAILURE = 2025; + + /** SSL/TLS error. */ + static const int IGNITE_ERR_SECURE_CONNECTION_FAILURE = 2026; + + /** Transaction already started by current thread. */ + static const int IGNITE_ERR_TX_THIS_THREAD = 2027; + + /** Generic transaction error. */ + static const int IGNITE_ERR_TX = 2028; + + + /** Unknown error. */ + static const int IGNITE_ERR_UNKNOWN = -1; + + /** + * Throw an error if code is not IGNITE_SUCCESS. + * + * @param err Error. + */ + static void ThrowIfNeeded(const IgniteError& err); + + /** + * Default constructor. + * Creates empty error. Code is IGNITE_SUCCESS and message is NULL. + */ + IgniteError(); + + /** + * Create error with specific code. Message is set to NULL. + * + * @param code Error code. + */ + IgniteError(const int32_t code); + + /** + * Create error with specific code and message. + * + * @param code Error code. + * @param msg Message. + */ + IgniteError(const int32_t code, const char* msg); + + /** + * Copy constructor. + * + * @param other Other instance. + */ + IgniteError(const IgniteError& other); + + /** + * Assignment operator. + * + * @param other Other instance. + * @return *this. + */ + IgniteError& operator=(const IgniteError& other); + + /** + * Destructor. + */ + ~IgniteError() IGNITE_NO_THROW; + + /** + * Get error code. + * + * @return Error code. + */ + int32_t GetCode() const; + + /** + * Get error message. + * + * @return Error message. Can be NULL. + */ + const char* GetText() const IGNITE_NO_THROW; + + /** + * Implementation of the standard std::exception::what() method. + * Synonym for GetText() method. + * + * @return Error message string. + */ + virtual const char* what() const IGNITE_NO_THROW; + + /** + * Initializes IgniteError instance from the JNI error. + * + * @param jniCode Error code. + * @param jniCls Error class. + * @param jniMsg Error message. + * @param err Error. Can not be NULL. + */ + static void SetError(const int jniCode, const char* jniCls, const char* jniMsg, IgniteError& err); + private: + /** Error code. */ + int32_t code; + + /** Error message. */ + char* msg; + }; + } +} + +#ifdef _MSC_VER +# pragma warning(pop) +#endif //_MSC_VER + +#endif //_IGNITE_ODBC_IGNITE_ERROR diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h new file mode 100644 index 000000000..3925aaf0a --- /dev/null +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -0,0 +1,641 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_JNI_JAVA +#define _IGNITE_ODBC_JNI_JAVA + +#include + +#include + +#include + +namespace ignite { + namespace odbc { + namespace jni { + namespace java { + + /* Handlers for callbacks from Java. */ + typedef int64_t(JNICALL* CacheStoreCreateHandler)(void* target, int64_t memPtr); + typedef int(JNICALL* CacheStoreInvokeHandler)(void* target, int64_t objPtr, + int64_t memPtr); + typedef void(JNICALL* CacheStoreDestroyHandler)(void* target, int64_t objPtr); + typedef int64_t(JNICALL* CacheStoreSessionCreateHandler)(void* target, + int64_t storePtr); + + typedef int64_t(JNICALL* CacheEntryFilterCreateHandler)(void* target, + int64_t memPtr); + typedef int(JNICALL* CacheEntryFilterApplyHandler)(void* target, int64_t ptr, + int64_t memPtr); + typedef void(JNICALL* CacheEntryFilterDestroyHandler)(void* target, + int64_t ptr); + + typedef void(JNICALL* CacheInvokeHandler)(void* target, int64_t inMemPtr, + int64_t outMemPtr); + + typedef void(JNICALL* ComputeTaskMapHandler)(void* target, int64_t taskPtr, + int64_t inMemPtr, + int64_t outMemPtr); + typedef int(JNICALL* ComputeTaskJobResultHandler)(void* target, int64_t taskPtr, + int64_t jobPtr, + int64_t memPtr); + typedef void(JNICALL* ComputeTaskReduceHandler)(void* target, int64_t taskPtr); + typedef void(JNICALL* ComputeTaskCompleteHandler)(void* target, int64_t taskPtr, + int64_t memPtr); + typedef int(JNICALL* ComputeJobSerializeHandler)(void* target, int64_t jobPtr, + int64_t memPtr); + typedef int64_t(JNICALL* ComputeJobCreateHandler)(void* target, int64_t memPtr); + typedef void(JNICALL* ComputeJobExecuteHandler)(void* target, int64_t jobPtr, + int cancel, int64_t memPtr); + typedef void(JNICALL* ComputeJobCancelHandler)(void* target, int64_t jobPtr); + typedef void(JNICALL* ComputeJobDestroyHandler)(void* target, int64_t jobPtr); + + typedef void(JNICALL* ContinuousQueryListenerApplyHandler)(void* target, + int64_t lsnrPtr, + int64_t memPtr); + typedef int64_t(JNICALL* ContinuousQueryFilterCreateHandler)(void* target, + int64_t memPtr); + typedef int(JNICALL* ContinuousQueryFilterApplyHandler)(void* target, + int64_t filterPtr, + int64_t memPtr); + typedef void(JNICALL* ContinuousQueryFilterReleaseHandler)(void* target, + int64_t filterPtr); + + typedef void(JNICALL* DataStreamerTopologyUpdateHandler)(void* target, + int64_t ldrPtr, + int64_t topVer, + int topSize); + typedef void(JNICALL* DataStreamerStreamReceiverInvokeHandler)( + void* target, int64_t ptr, void* cache, int64_t memPtr, + unsigned char keepPortable); + + typedef void(JNICALL* FutureByteResultHandler)(void* target, int64_t futAddr, + int res); + typedef void(JNICALL* FutureBoolResultHandler)(void* target, int64_t futAddr, + int res); + typedef void(JNICALL* FutureShortResultHandler)(void* target, int64_t futAddr, + int res); + typedef void(JNICALL* FutureCharResultHandler)(void* target, int64_t futAddr, + int res); + typedef void(JNICALL* FutureIntResultHandler)(void* target, int64_t futAddr, + int res); + typedef void(JNICALL* FutureFloatResultHandler)(void* target, int64_t futAddr, + float res); + typedef void(JNICALL* FutureLongResultHandler)(void* target, int64_t futAddr, + int64_t res); + typedef void(JNICALL* FutureDoubleResultHandler)(void* target, int64_t futAddr, + double res); + typedef void(JNICALL* FutureObjectResultHandler)(void* target, int64_t futAddr, + int64_t memPtr); + typedef void(JNICALL* FutureNullResultHandler)(void* target, int64_t futAddr); + typedef void(JNICALL* FutureErrorHandler)(void* target, int64_t futAddr, + int64_t memPtr); + + typedef void(JNICALL* LifecycleEventHandler)(void* target, int64_t ptr, + int evt); + + typedef void(JNICALL* MemoryReallocateHandler)(void* target, int64_t memPtr, + int cap); + + typedef int64_t(JNICALL* MessagingFilterCreateHandler)(void* target, + int64_t memPtr); + typedef int(JNICALL* MessagingFilterApplyHandler)(void* target, int64_t ptr, + int64_t memPtr); + typedef void(JNICALL* MessagingFilterDestroyHandler)(void* target, int64_t ptr); + + typedef int64_t(JNICALL* EventFilterCreateHandler)(void* target, + int64_t memPtr); + typedef int(JNICALL* EventFilterApplyHandler)(void* target, int64_t ptr, + int64_t memPtr); + typedef void(JNICALL* EventFilterDestroyHandler)(void* target, int64_t ptr); + + typedef int64_t(JNICALL* ServiceInitHandler)(void* target, int64_t memPtr); + typedef void(JNICALL* ServiceExecuteHandler)(void* target, int64_t svcPtr, + int64_t memPtr); + typedef void(JNICALL* ServiceCancelHandler)(void* target, int64_t svcPtr, + int64_t memPtr); + typedef void(JNICALL* ServiceInvokeMethodHandler)(void* target, int64_t svcPtr, + int64_t inMemPtr, + int64_t outMemPtr); + typedef int(JNICALL* ClusterNodeFilterApplyHandler)(void* target, + int64_t memPtr); + + typedef int64_t(JNICALL* NodeInfoHandler)(void* target, int64_t memPtr); + + typedef void(JNICALL* OnStartHandler)(void* target, void* proc, int64_t memPtr); + typedef void(JNICALL* OnStopHandler)(void* target); + typedef void(JNICALL* ErrorHandler)(void* target, int errCode, + const char* errClsChars, int errClsCharsLen, + const char* errMsgChars, int errMsgCharsLen, + const char* stackTraceChars, + int stackTraceCharsLen, void* errData, + int errDataLen); + + typedef int64_t(JNICALL* ExtensionCallbackInLongOutLongHandler)(void* target, + int typ, + int64_t arg1); + typedef int64_t(JNICALL* ExtensionCallbackInLongLongOutLongHandler)( + void* target, int typ, int64_t arg1, int64_t arg2); + + typedef void(JNICALL* OnClientDisconnectedHandler)(void* target); + typedef void(JNICALL* OnClientReconnectedHandler)( + void* target, unsigned char clusterRestarted); + + typedef int64_t(JNICALL* AffinityFunctionInitHandler)(void* target, + int64_t memPtr, + void* baseFunc); + typedef int(JNICALL* AffinityFunctionPartitionHandler)(void* target, + int64_t ptr, + int64_t memPtr); + typedef void(JNICALL* AffinityFunctionAssignPartitionsHandler)( + void* target, int64_t ptr, int64_t inMemPtr, int64_t outMemPtr); + typedef void(JNICALL* AffinityFunctionRemoveNodeHandler)(void* target, + int64_t ptr, + int64_t memPtr); + typedef void(JNICALL* AffinityFunctionDestroyHandler)(void* target, + int64_t ptr); + + typedef void(JNICALL* ConsoleWriteHandler)(const char* chars, int charsLen, + unsigned char isErr); + + typedef void(JNICALL* LoggerLogHandler)( + void* target, int level, const char* messageChars, int messageCharsLen, + const char* categoryChars, int categoryCharsLen, const char* errorInfoChars, + int errorInfoCharsLen, int64_t memPtr); + typedef bool(JNICALL* LoggerIsLevelEnabledHandler)(void* target, int level); + + typedef int64_t(JNICALL* InLongOutLongHandler)(void* target, int type, + int64_t val); + typedef int64_t(JNICALL* InLongLongLongObjectOutLongHandler)( + void* target, int type, int64_t val1, int64_t val2, int64_t val3, + void* arg); + + /** + * Is Java 9 or later is used. + * + * @return true if the Java 9 or later is in use. + */ + bool IGNITE_IMPORT_EXPORT IsJava9OrLater(); + + /** + * JNI handlers holder. + */ + struct JniHandlers { + void* target; + + ErrorHandler error; + + LoggerLogHandler loggerLog; + LoggerIsLevelEnabledHandler loggerIsLevelEnabled; + + InLongOutLongHandler inLongOutLong; + InLongLongLongObjectOutLongHandler inLongLongLongObjectOutLong; + }; + + /** + * JNI Java members. + */ + struct JniJavaMembers { + jclass c_Class; + jmethodID m_Class_getName; + + jclass c_Throwable; + jmethodID m_Throwable_getMessage; + jmethodID m_Throwable_printStackTrace; + + jclass c_PlatformUtils; + jmethodID m_PlatformUtils_getFullStackTrace; + + /** + * Constructor. + */ + void Initialize(JNIEnv* env); + + /** + * Destroy members releasing all allocated classes. + */ + void Destroy(JNIEnv* env); + + /** + * Write error information. + */ + bool WriteErrorInfo(JNIEnv* env, char** errClsName, int* errClsNameLen, + char** errMsg, int* errMsgLen, char** stackTrace, + int* stackTraceLen); + }; + + /** + * JNI members. + */ + struct JniMembers { + jclass c_DocumentDbConnectionProperties; + jmethodID m_DocumentDbConnectionPropertiesGetPropertiesFromConnectionString; + + jclass c_DocumentDbConnection; + jmethodID m_DocumentDbConnectionInit; + jmethodID m_DocumentDbClose; + + jclass c_DriverManager; + jmethodID m_DriverManagerGetConnection; + + jclass c_JavaSqlConnection; + jmethodID m_JavaSqlConnectionClose; + + jclass c_IgniteException; + + jclass c_PlatformIgnition; + jmethodID m_PlatformIgnition_start; + jmethodID m_PlatformIgnition_instance; + jmethodID m_PlatformIgnition_environmentPointer; + jmethodID m_PlatformIgnition_stop; + jmethodID m_PlatformIgnition_stopAll; + + jclass c_PlatformTarget; + jmethodID m_PlatformTarget_inLongOutLong; + jmethodID m_PlatformTarget_inStreamOutLong; + jmethodID m_PlatformTarget_inStreamOutObject; + jmethodID m_PlatformTarget_outStream; + jmethodID m_PlatformTarget_outObject; + jmethodID m_PlatformTarget_inStreamAsync; + jmethodID m_PlatformTarget_inStreamOutObjectAsync; + jmethodID m_PlatformTarget_inStreamOutStream; + jmethodID m_PlatformTarget_inObjectStreamOutObjectStream; + + jclass c_PlatformUtils; + jmethodID m_PlatformUtils_reallocate; + jmethodID m_PlatformUtils_errData; + + /** + * Constructor. + */ + void Initialize(JNIEnv* env); + + /** + * Destroy members releasing all allocated classes. + */ + void Destroy(JNIEnv* env); + }; + + /** + * JNI JVM wrapper. + */ + class IGNITE_IMPORT_EXPORT JniJvm { + public: + /** + * Default constructor for uninitialized JVM. + */ + JniJvm(); + + /** + * Constructor. + * + * @param jvm JVM. + * @param javaMembers Java members. + * @param members Members. + */ + JniJvm(JavaVM* jvm, JniJavaMembers javaMembers, JniMembers members); + + /** + * Get JVM. + * + * @param JVM. + */ + JavaVM* GetJvm(); + + /** + * Get Java members. + * + * @param Java members. + */ + JniJavaMembers& GetJavaMembers(); + + /** + * Get members. + * + * @param Members. + */ + JniMembers& GetMembers(); + + private: + /** JVM. */ + JavaVM* jvm; + + /** Java members. */ + JniJavaMembers javaMembers; + + /** Members. */ + JniMembers members; + }; + + /** + * JNI error information. + */ + struct IGNITE_IMPORT_EXPORT JniErrorInfo { + int code; + char* errCls = nullptr; + char* errMsg = nullptr; + + /** + * Default constructor. Creates empty error info. + */ + JniErrorInfo(); + + /** + * Constructor. + * + * @param code Code. + * @param errCls Error class. + * @param errMsg Error message. + */ + JniErrorInfo(int code, const char* errCls, const char* errMsg); + + /** + * Copy constructor. + * + * @param other Other instance. + */ + JniErrorInfo(const JniErrorInfo& other); + + /** + * Assignment operator overload. + * + * @param other Other instance. + * @return This instance. + */ + JniErrorInfo& operator=(const JniErrorInfo& other); + + /** + * Destructor. + */ + ~JniErrorInfo(); + }; + + /** + * Unmanaged context. + */ + class IGNITE_IMPORT_EXPORT JniContext { + public: + static JniContext* Create(char** opts, int optsLen, JniHandlers hnds); + static JniContext* Create(char** opts, int optsLen, JniHandlers hnds, + JniErrorInfo* errInfo); + static int Reallocate(int64_t memPtr, int cap); + static void Detach(); + static void Release(jobject obj); + static void SetConsoleHandler(ConsoleWriteHandler consoleHandler); + static int RemoveConsoleHandler(ConsoleWriteHandler consoleHandler); + + jobject DocumentDbConnect(const char* connectionString, + JniErrorInfo* errInfo); + + void DocumentDbDisconnect(const jobject connection, JniErrorInfo* errInfo); + + int64_t TargetInLongOutLong(jobject obj, int type, int64_t memPtr, + JniErrorInfo* errInfo = NULL); + int64_t TargetInStreamOutLong(jobject obj, int type, int64_t memPtr, + JniErrorInfo* errInfo = NULL); + void TargetInStreamOutStream(jobject obj, int opType, int64_t inMemPtr, + int64_t outMemPtr, + JniErrorInfo* errInfo = NULL); + jobject TargetInStreamOutObject(jobject obj, int type, int64_t memPtr, + JniErrorInfo* errInfo = NULL); + jobject TargetInObjectStreamOutObjectStream(jobject obj, int opType, + void* arg, int64_t inMemPtr, + int64_t outMemPtr, + JniErrorInfo* errInfo = NULL); + void TargetOutStream(jobject obj, int opType, int64_t memPtr, + JniErrorInfo* errInfo = NULL); + jobject TargetOutObject(jobject obj, int opType, + JniErrorInfo* errInfo = NULL); + void TargetInStreamAsync(jobject obj, int type, int64_t memPtr, + JniErrorInfo* errInfo = NULL); + jobject TargetInStreamOutObjectAsync(jobject obj, int type, int64_t memPtr, + JniErrorInfo* errInfo = NULL); + + jobject CacheOutOpQueryCursor(jobject obj, int type, int64_t memPtr, + JniErrorInfo* errInfo = NULL); + jobject CacheOutOpContinuousQuery(jobject obj, int type, int64_t memPtr, + JniErrorInfo* errInfo = NULL); + + jobject Acquire(jobject obj); + + void DestroyJvm(); + void ThrowToJava(char* errMsg); + + private: + JniJvm* jvm; + JniHandlers hnds; + + JniContext(JniJvm* jvm, JniHandlers hnds); + + JNIEnv* Attach(); + void ExceptionCheck(JNIEnv* env); + void ExceptionCheck(JNIEnv* env, JniErrorInfo* errInfo); + jobject LocalToGlobal(JNIEnv* env, jobject obj); + }; + + JNIEXPORT jlong JNICALL JniCacheStoreCreate(JNIEnv* env, jclass cls, + jlong envPtr, jlong memPtr); + JNIEXPORT jint JNICALL JniCacheStoreInvoke(JNIEnv* env, jclass cls, + jlong envPtr, jlong objPtr, + jlong memPtr); + JNIEXPORT void JNICALL JniCacheStoreDestroy(JNIEnv* env, jclass cls, + jlong envPtr, jlong objPtr); + JNIEXPORT jlong JNICALL JniCacheStoreSessionCreate(JNIEnv* env, jclass cls, + jlong envPtr, + jlong storePtr); + + JNIEXPORT jlong JNICALL JniCacheEntryFilterCreate(JNIEnv* env, jclass cls, + jlong envPtr, jlong memPtr); + JNIEXPORT jint JNICALL JniCacheEntryFilterApply(JNIEnv* env, jclass cls, + jlong envPtr, jlong objPtr, + jlong memPtr); + JNIEXPORT void JNICALL JniCacheEntryFilterDestroy(JNIEnv* env, jclass cls, + jlong envPtr, jlong objPtr); + + JNIEXPORT void JNICALL JniCacheInvoke(JNIEnv* env, jclass cls, jlong envPtr, + jlong inMemPtr, jlong outMemPtr); + + JNIEXPORT void JNICALL JniComputeTaskMap(JNIEnv* env, jclass cls, jlong envPtr, + jlong taskPtr, jlong inMemPtr, + jlong outMemPtr); + JNIEXPORT jint JNICALL JniComputeTaskJobResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong taskPtr, + jlong jobPtr, jlong memPtr); + JNIEXPORT void JNICALL JniComputeTaskReduce(JNIEnv* env, jclass cls, + jlong envPtr, jlong taskPtr); + JNIEXPORT void JNICALL JniComputeTaskComplete(JNIEnv* env, jclass cls, + jlong envPtr, jlong taskPtr, + jlong memPtr); + JNIEXPORT jint JNICALL JniComputeJobSerialize(JNIEnv* env, jclass cls, + jlong envPtr, jlong jobPtr, + jlong memPtr); + JNIEXPORT jlong JNICALL JniComputeJobCreate(JNIEnv* env, jclass cls, + jlong envPtr, jlong memPtr); + JNIEXPORT void JNICALL JniComputeJobExecute(JNIEnv* env, jclass cls, + jlong envPtr, jlong jobPtr, + jint cancel, jlong memPtr); + JNIEXPORT void JNICALL JniComputeJobCancel(JNIEnv* env, jclass cls, + jlong envPtr, jlong jobPtr); + JNIEXPORT void JNICALL JniComputeJobDestroy(JNIEnv* env, jclass cls, + jlong envPtr, jlong jobPtr); + + JNIEXPORT void JNICALL JniContinuousQueryListenerApply(JNIEnv* env, jclass cls, + jlong envPtr, + jlong cbPtr, + jlong memPtr); + JNIEXPORT jlong JNICALL JniContinuousQueryFilterCreate(JNIEnv* env, jclass cls, + jlong envPtr, + jlong memPtr); + JNIEXPORT jint JNICALL JniContinuousQueryFilterApply(JNIEnv* env, jclass cls, + jlong envPtr, + jlong filterPtr, + jlong memPtr); + JNIEXPORT void JNICALL JniContinuousQueryFilterRelease(JNIEnv* env, jclass cls, + jlong envPtr, + jlong filterPtr); + + JNIEXPORT void JNICALL JniDataStreamerTopologyUpdate(JNIEnv* env, jclass cls, + jlong envPtr, jlong ldrPtr, + jlong topVer, + jint topSize); + JNIEXPORT void JNICALL JniDataStreamerStreamReceiverInvoke( + JNIEnv* env, jclass cls, jlong envPtr, jlong ptr, jobject cache, + jlong memPtr, jboolean keepPortable); + + JNIEXPORT void JNICALL JniFutureByteResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong futPtr, + jint res); + JNIEXPORT void JNICALL JniFutureBoolResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong futPtr, + jint res); + JNIEXPORT void JNICALL JniFutureShortResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong futPtr, + jint res); + JNIEXPORT void JNICALL JniFutureCharResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong futPtr, + jint res); + JNIEXPORT void JNICALL JniFutureIntResult(JNIEnv* env, jclass cls, jlong envPtr, + jlong futPtr, jint res); + JNIEXPORT void JNICALL JniFutureFloatResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong futPtr, + jfloat res); + JNIEXPORT void JNICALL JniFutureLongResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong futPtr, + jlong res); + JNIEXPORT void JNICALL JniFutureDoubleResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong futPtr, + jdouble res); + JNIEXPORT void JNICALL JniFutureObjectResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong futPtr, + jlong memPtr); + JNIEXPORT void JNICALL JniFutureNullResult(JNIEnv* env, jclass cls, + jlong envPtr, jlong futPtr); + JNIEXPORT void JNICALL JniFutureError(JNIEnv* env, jclass cls, jlong envPtr, + jlong futPtr, jlong memPtr); + + JNIEXPORT void JNICALL JniLifecycleEvent(JNIEnv* env, jclass cls, jlong envPtr, + jlong ptr, jint evt); + + JNIEXPORT void JNICALL JniMemoryReallocate(JNIEnv* env, jclass cls, + jlong envPtr, jlong memPtr, + jint cap); + + JNIEXPORT jlong JNICALL JniMessagingFilterCreate(JNIEnv* env, jclass cls, + jlong envPtr, jlong memPtr); + JNIEXPORT jint JNICALL JniMessagingFilterApply(JNIEnv* env, jclass cls, + jlong envPtr, jlong ptr, + jlong memPtr); + JNIEXPORT void JNICALL JniMessagingFilterDestroy(JNIEnv* env, jclass cls, + jlong envPtr, jlong ptr); + + JNIEXPORT jlong JNICALL JniEventFilterCreate(JNIEnv* env, jclass cls, + jlong envPtr, jlong memPtr); + JNIEXPORT jint JNICALL JniEventFilterApply(JNIEnv* env, jclass cls, + jlong envPtr, jlong ptr, + jlong memPtr); + JNIEXPORT void JNICALL JniEventFilterDestroy(JNIEnv* env, jclass cls, + jlong envPtr, jlong ptr); + + JNIEXPORT jlong JNICALL JniServiceInit(JNIEnv* env, jclass cls, jlong envPtr, + jlong memPtr); + JNIEXPORT void JNICALL JniServiceExecute(JNIEnv* env, jclass cls, jlong envPtr, + jlong svcPtr, jlong memPtr); + JNIEXPORT void JNICALL JniServiceCancel(JNIEnv* env, jclass cls, jlong envPtr, + jlong svcPtr, jlong memPtr); + JNIEXPORT void JNICALL JniServiceInvokeMethod(JNIEnv* env, jclass cls, + jlong envPtr, jlong svcPtr, + jlong inMemPtr, jlong outMemPtr); + JNIEXPORT jint JNICALL JniClusterNodeFilterApply(JNIEnv* env, jclass cls, + jlong envPtr, jlong memPtr); + + JNIEXPORT jlong JNICALL JniNodeInfo(JNIEnv* env, jclass cls, jlong envPtr, + jlong memPtr); + + JNIEXPORT void JNICALL JniOnStart(JNIEnv* env, jclass cls, jlong envPtr, + jobject proc, jlong memPtr); + JNIEXPORT void JNICALL JniOnStop(JNIEnv* env, jclass cls, jlong envPtr); + + JNIEXPORT jlong JNICALL JniExtensionCallbackInLongOutLong(JNIEnv* env, + jclass cls, + jlong envPtr, + jint typ, jlong arg1); + JNIEXPORT jlong JNICALL JniExtensionCallbackInLongLongOutLong( + JNIEnv* env, jclass cls, jlong envPtr, jint typ, jlong arg1, jlong arg2); + + JNIEXPORT void JNICALL JniOnClientDisconnected(JNIEnv* env, jclass cls, + jlong envPtr); + JNIEXPORT void JNICALL JniOnClientReconnected(JNIEnv* env, jclass cls, + jlong envPtr, + jboolean clusterRestarted); + + JNIEXPORT jlong JNICALL JniAffinityFunctionInit(JNIEnv* env, jclass cls, + jlong envPtr, jlong memPtr, + jobject baseFunc); + JNIEXPORT jint JNICALL JniAffinityFunctionPartition(JNIEnv* env, jclass cls, + jlong envPtr, jlong ptr, + jlong memPtr); + JNIEXPORT void JNICALL + JniAffinityFunctionAssignPartitions(JNIEnv* env, jclass cls, jlong envPtr, + jlong ptr, jlong inMemPtr, jlong outMemPtr); + JNIEXPORT void JNICALL JniAffinityFunctionRemoveNode(JNIEnv* env, jclass cls, + jlong envPtr, jlong ptr, + jlong memPtr); + JNIEXPORT void JNICALL JniAffinityFunctionDestroy(JNIEnv* env, jclass cls, + jlong envPtr, jlong ptr); + + JNIEXPORT void JNICALL JniConsoleWrite(JNIEnv* env, jclass cls, jstring str, + jboolean isErr); + + JNIEXPORT void JNICALL JniLoggerLog(JNIEnv* env, jclass cls, jlong envPtr, + jint level, jstring message, + jstring category, jstring errorInfo, + jlong memPtr); + JNIEXPORT jboolean JNICALL JniLoggerIsLevelEnabled(JNIEnv* env, jclass cls, + jlong envPtr, jint level); + + JNIEXPORT jlong JNICALL JniInLongOutLong(JNIEnv* env, jclass cls, jlong envPtr, + jint type, jlong val); + JNIEXPORT jlong JNICALL JniInLongLongLongObjectOutLong(JNIEnv* env, jclass cls, + jlong envPtr, jint type, + jlong val1, jlong val2, + jlong val3, jobject arg); + } // namespace java + } // namespace jni + } // namespace odbc +} // namespace ignite + +#endif //_IGNITE_ODBC_JNI_JAVA diff --git a/src/odbc/include/ignite/odbc/jni/utils.h b/src/odbc/include/ignite/odbc/jni/utils.h new file mode 100644 index 000000000..508a40756 --- /dev/null +++ b/src/odbc/include/ignite/odbc/jni/utils.h @@ -0,0 +1,193 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _IGNITE_ODBC_JNI_UTILS +#define _IGNITE_ODBC_JNI_UTILS + +#include + +#include +#include +#include + +namespace ignite +{ + namespace odbc + { + namespace jni + { + /** + * Helper class to manage attached threads. + */ + class AttachHelper + { + public: + /** + * Destructor. + */ + ~AttachHelper(); + + /** + * Callback invoked on successful thread attach ot JVM. + */ + static void OnThreadAttach(); + }; + + /** + * Represents global reference to Java object. + */ + class IGNITE_IMPORT_EXPORT JavaGlobalRef + { + public: + /** + * Default constructor + */ + JavaGlobalRef() : + obj(NULL) + { + // No-op. + } + + /** + * Constructor + * + * @param ctx JNI context. + * @param obj Java object. + */ + JavaGlobalRef(common::concurrent::SharedPointer& ctx, jobject obj) + : obj(NULL) + { + Init(ctx, obj); + } + + /** + * Copy constructor + * + * @param other Other instance. + */ + JavaGlobalRef(const JavaGlobalRef& other) + : obj(NULL) + { + Init(other.ctx, other.obj); + } + + /** + * Assignment operator. + * + * @param other Other instance. + * @return *this. + */ + JavaGlobalRef& operator=(const JavaGlobalRef& other) + { + if (this != &other) + { + java::JniContext::Release(obj); + + Init(other.ctx, other.obj); + } + + return *this; + } + + /** + * Destructor. + */ + ~JavaGlobalRef() + { + java::JniContext::Release(obj); + } + + /** + * Get object. + * + * @return Object. + */ + jobject Get() + { + return obj; + } + + private: + /** Initializer */ + void Init(const common::concurrent::SharedPointer& ctx0, jobject obj0) { + ctx = ctx0; + + if (ctx.IsValid()) + this->obj = ctx.Get()->Acquire(obj0); + } + + /** Context. */ + common::concurrent::SharedPointer ctx; + + /** Object. */ + jobject obj; + }; + + /** + * Attempts to find JVM library to load it into the process later. + * First search is performed using the passed path argument (is not NULL). + * Then JRE_HOME is evaluated. Last, JAVA_HOME is evaluated. + * + * @param path Explicitly defined path (optional). + * @return Path to the file. Empty string if the library was not found. + */ + IGNITE_IMPORT_EXPORT std::string FindJvmLibrary(const std::string& path); + + /** + * Load JVM library into the process. + * + * @param path Optional path to the library. + * @return Whether load was successful. + */ + IGNITE_IMPORT_EXPORT bool LoadJvmLibrary(const std::string& path); + + /** + * Helper function to create classpath based on Ignite home directory. + * + * @param home Home directory; expected to be valid. + * @param forceTest Force test classpath. + * @return Classpath. + */ + IGNITE_IMPORT_EXPORT std::string CreateDocumentDbHomeClasspath(const std::string& home, bool forceTest); + + /** + * Create Ignite classpath based on user input and home directory. + * + * @param usrCp User's classpath. + * @param home Ignite home directory. + * @return Classpath. + */ + IGNITE_IMPORT_EXPORT std::string CreateDocumentDbClasspath(const std::string& usrCp, const std::string& home); + + /** + * Resolve DOCUMENTDB_HOME directory. Resolution is performed in several + * steps: + * 1) Check for path provided as argument. + * 2) Check for environment variable. + * 3) Check for current working directory. + * Result of these checks are evaluated based on existence of certain + * predefined folders inside possible Ignite home. If they are found, + * IGNITE_HOME is considered resolved. + * + * @param path Optional path to evaluate. + * @return Resolved Ignite home. + */ + IGNITE_IMPORT_EXPORT std::string ResolveDocumentDbHome(const std::string& path = ""); + } + } +} + +#endif //_IGNITE_ODBC_JNI_UTILS diff --git a/src/odbc/include/ignite/odbc/log.h b/src/odbc/include/ignite/odbc/log.h index 5a6dafcb9..2e361ea20 100644 --- a/src/odbc/include/ignite/odbc/log.h +++ b/src/odbc/include/ignite/odbc/log.h @@ -22,8 +22,8 @@ #include #include -#include "ignite/common/common.h" -#include "ignite/common/concurrent.h" +#include "ignite/odbc/common/common.h" +#include "ignite/odbc/common/concurrent.h" # define LOG_MSG(param) \ if (ignite::odbc::Logger* p = ignite::odbc::Logger::Get()) \ @@ -112,7 +112,7 @@ namespace ignite IGNITE_NO_COPY_ASSIGNMENT(Logger); /** Mutex for writes synchronization. */ - ignite::common::concurrent::CriticalSection mutex; + odbc::common::concurrent::CriticalSection mutex; /** File stream. */ std::ofstream stream; diff --git a/src/odbc/include/ignite/odbc/meta/column_meta.h b/src/odbc/include/ignite/odbc/meta/column_meta.h index 5144fa3b8..d38ed2b9c 100644 --- a/src/odbc/include/ignite/odbc/meta/column_meta.h +++ b/src/odbc/include/ignite/odbc/meta/column_meta.h @@ -75,7 +75,7 @@ namespace ignite /** * Default constructor. */ - ColumnMeta() + ColumnMeta() : dataType(), nullability(), precision(), scale() { // No-op. } diff --git a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h index a2f531863..1cb69f741 100644 --- a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h +++ b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h @@ -40,7 +40,7 @@ namespace ignite /** * Default constructor. */ - PrimaryKeyMeta() + PrimaryKeyMeta() : keySeq(0) { // No-op. } diff --git a/src/odbc/include/ignite/odbc/odbc_error.h b/src/odbc/include/ignite/odbc/odbc_error.h index 9b3b48d4f..07664329d 100644 --- a/src/odbc/include/ignite/odbc/odbc_error.h +++ b/src/odbc/include/ignite/odbc/odbc_error.h @@ -21,7 +21,7 @@ #include #include -#include +#include namespace ignite { @@ -102,13 +102,13 @@ namespace ignite std::string errMessage; }; - typedef common::Unexpected OdbcUnexpected; + typedef odbc::common::Unexpected OdbcUnexpected; /** * Expected specialization for OdbcError. */ template - struct OdbcExpected : common::Expected + struct OdbcExpected : odbc::common::Expected { OdbcExpected(const R& res) : common::Expected(res) diff --git a/src/odbc/include/ignite/odbc/utility.h b/src/odbc/include/ignite/odbc/utility.h index 152da6635..cf31de0d6 100644 --- a/src/odbc/include/ignite/odbc/utility.h +++ b/src/odbc/include/ignite/odbc/utility.h @@ -26,8 +26,8 @@ #include -#include -#include +#include +#include #include "ignite/impl/binary/binary_reader_impl.h" #include "ignite/impl/binary/binary_writer_impl.h" @@ -83,7 +83,7 @@ namespace ignite * @param reader Reader. * @param decimal Decimal value. */ - void ReadDecimal(impl::binary::BinaryReaderImpl& reader, common::Decimal& decimal); + void ReadDecimal(impl::binary::BinaryReaderImpl& reader, odbc::common::Decimal& decimal); /** * Write decimal value using writer. @@ -91,7 +91,7 @@ namespace ignite * @param writer Writer. * @param decimal Decimal value. */ - void WriteDecimal(impl::binary::BinaryWriterImpl& writer, const common::Decimal& decimal); + void WriteDecimal(impl::binary::BinaryWriterImpl& writer, const odbc::common::Decimal& decimal); /** * Convert SQL string buffer to std::string. diff --git a/src/odbc/install/install_amd64.cmd b/src/odbc/install/install_amd64.cmd index 6c7de9393..5795e0cf8 100644 --- a/src/odbc/install/install_amd64.cmd +++ b/src/odbc/install/install_amd64.cmd @@ -29,7 +29,7 @@ if exist %ODBC_AMD64% ( if [%ODBC_X86%] == [] ( echo warning: 32-bit driver is not specified. If you want to install 32-bit driver please specify path to it as a second argument. pause - exit /b 1 + exit /b 0 ) if exist %ODBC_X86% ( @@ -44,5 +44,6 @@ if exist %ODBC_X86% ( reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\ODBC\ODBCINST.INI\ODBC Drivers" /v "Apache Ignite" /t REG_SZ /d "Installed" /f ) else ( echo warning: 32-bit driver can not be found: %ODBC_X86% + exit /b 1 ) diff --git a/src/odbc/os/linux/include/ignite/odbc/common/common.h b/src/odbc/os/linux/include/ignite/odbc/common/common.h new file mode 100644 index 000000000..5e3924c3a --- /dev/null +++ b/src/odbc/os/linux/include/ignite/odbc/common/common.h @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_COMMON_COMMON +#define _IGNITE_ODBC_COMMON_COMMON + +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + +#if (defined(__GNUC__) && ((__GNUC__ > 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ > 2))) || __has_attribute(visibility) +# define IGNITE_EXPORT __attribute__((visibility("default"))) +# define IGNITE_IMPORT __attribute__((visibility("default"))) +#else +# define IGNITE_EXPORT +# define IGNITE_IMPORT +#endif + +#define IGNITE_CALL + +#ifdef IGNITE_IMPL +# define IGNITE_IMPORT_EXPORT IGNITE_EXPORT +#else +# define IGNITE_IMPORT_EXPORT IGNITE_IMPORT +#endif + +#if (__cplusplus >= 201103L) +# define IGNITE_NO_THROW noexcept +#else +# define IGNITE_NO_THROW throw() +#endif + +#define IGNITE_UNUSED(x) ((void) x) + +/** + * Common construction to disable copy constructor and assignment for class. + */ +#define IGNITE_NO_COPY_ASSIGNMENT(cls) \ + cls(const cls& src); \ + cls& operator= (const cls& other) + +#endif //_IGNITE_ODBC_COMMON_COMMON diff --git a/src/odbc/os/linux/include/ignite/odbc/common/concurrent_os.h b/src/odbc/os/linux/include/ignite/odbc/common/concurrent_os.h new file mode 100644 index 000000000..74711337b --- /dev/null +++ b/src/odbc/os/linux/include/ignite/odbc/common/concurrent_os.h @@ -0,0 +1,701 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_COMMON_CONCURRENT_OS +#define _IGNITE_ODBC_COMMON_CONCURRENT_OS + +#include +#include +#include + +#include + +#include +#include + +#include + +namespace ignite +{ + namespace odbc + { + namespace common + { + namespace concurrent + { + /** + * Static class to manage memory visibility semantics. + */ + class IGNITE_IMPORT_EXPORT Memory { + public: + /** + * Full fence. + */ + static void Fence(); + }; + + /** + * Critical section. + */ + class IGNITE_IMPORT_EXPORT CriticalSection + { + friend class ConditionVariable; + public: + /** + * Constructor. + */ + CriticalSection(); + + /** + * Destructor. + */ + ~CriticalSection(); + + /** + * Enter critical section. + */ + void Enter(); + + /** + * Leave critical section. + */ + void Leave(); + private: + pthread_mutex_t mux; + + IGNITE_NO_COPY_ASSIGNMENT(CriticalSection); + }; + + class IGNITE_IMPORT_EXPORT ReadWriteLock + { + public: + /** + * Constructor. + */ + ReadWriteLock(); + + /** + * Destructor. + */ + ~ReadWriteLock(); + + /** + * Lock in exclusive mode. + */ + void LockExclusive(); + + /** + * Release in exclusive mode. + */ + void ReleaseExclusive(); + + /** + * Lock in shared mode. + */ + void LockShared(); + + /** + * Release in shared mode. + */ + void ReleaseShared(); + + private: + /** Lock. */ + pthread_rwlock_t lock; + + IGNITE_NO_COPY_ASSIGNMENT(ReadWriteLock); + }; + + /** + * Special latch with count = 1. + */ + class IGNITE_IMPORT_EXPORT SingleLatch + { + public: + /** + * Constructor. + */ + SingleLatch(); + + /** + * Destructor. + */ + ~SingleLatch(); + + /** + * Perform the countdown. + */ + void CountDown(); + + /** + * Await the countdown. + */ + void Await(); + private: + /** Mutex. */ + pthread_mutex_t mux; + + /** Condition. */ + pthread_cond_t cond; + + /** Ready flag. */ + bool ready; + + IGNITE_NO_COPY_ASSIGNMENT(SingleLatch); + }; + + /** + * Primitives for atomic access. + */ + class IGNITE_IMPORT_EXPORT Atomics + { + public: + /** + * Update the 32-bit integer value if it is equal to expected value. + * + * @param ptr Pointer. + * @param expVal Expected value. + * @param newVal New value. + * @return True if update occurred as a result of this call, false otherwise. + */ + static bool CompareAndSet32(int32_t* ptr, int32_t expVal, int32_t newVal); + + /** + * Update the 32-bit integer value if it is equal to expected value. + * + * @param ptr Pointer. + * @param expVal Expected value. + * @param newVal New value. + * @return Value which were observed during CAS attempt. + */ + static int32_t CompareAndSet32Val(int32_t* ptr, int32_t expVal, int32_t newVal); + + /** + * Increment 32-bit integer and return new value. + * + * @param ptr Pointer. + * @return Value after increment. + */ + static int32_t IncrementAndGet32(int32_t* ptr); + + /** + * Decrement 32-bit integer and return new value. + * + * @param ptr Pointer. + * @return Value after decrement. + */ + static int32_t DecrementAndGet32(int32_t* ptr); + + /** + * Update the 64-bit integer value if it is equal to expected value. + * + * @param ptr Pointer. + * @param expVal Expected value. + * @param newVal New value. + * @return True if update occurred as a result of this call, false otherwise. + */ + static bool CompareAndSet64(int64_t* ptr, int64_t expVal, int64_t newVal); + + /** + * Update the 64-bit integer value if it is equal to expected value. + * + * @param ptr Pointer. + * @param expVal Expected value. + * @param newVal New value. + * @return Value which were observed during CAS attempt. + */ + static int64_t CompareAndSet64Val(int64_t* ptr, int64_t expVal, int64_t newVal); + + /** + * Increment 64-bit integer and return new value. + * + * @param ptr Pointer. + * @return Value after increment. + */ + static int64_t IncrementAndGet64(int64_t* ptr); + + /** + * Decrement 64-bit integer and return new value. + * + * @param ptr Pointer. + * @return Value after decrement. + */ + static int64_t DecrementAndGet64(int64_t* ptr); + }; + + /** + * Thread-local entry. + */ + class IGNITE_IMPORT_EXPORT ThreadLocalEntry + { + public: + /** + * Virtual destructor to allow for correct typed entries cleanup. + */ + virtual ~ThreadLocalEntry() + { + // No-op. + } + }; + + /** + * Typed thread-local entry. + */ + template + class IGNITE_IMPORT_EXPORT ThreadLocalTypedEntry : public ThreadLocalEntry + { + public: + /** + * Constructor. + * + * @param val Value. + */ + ThreadLocalTypedEntry(T val) : val(val) + { + // No-op. + } + + ~ThreadLocalTypedEntry() + { + // No-op. + } + + /** + * Get value. + * + * @return Value. + */ + T Get() + { + return val; + } + private: + /** Value. */ + T val; + }; + + /** + * Thread-local abstraction. + */ + class IGNITE_IMPORT_EXPORT ThreadLocal + { + public: + /** + * Get next available index to be used in thread-local storage. + * + * @return Index. + */ + static int32_t NextIndex(); + + /** + * Get value by index. + * + * @param idx Index. + * @return Value associated with the index or NULL. + */ + template + static T Get(int32_t idx) + { + void* linuxVal = Get0(); + + if (linuxVal) + { + std::map* map = + static_cast*>(linuxVal); + + ThreadLocalTypedEntry* entry = static_cast*>((*map)[idx]); + + if (entry) + return entry->Get(); + } + + return T(); + } + + /** + * Set value at the given index. + * + * @param idx Index. + * @param val Value to be associated with the index. + */ + template + static void Set(int32_t idx, const T& val) + { + void* linuxVal = Get0(); + + if (linuxVal) + { + std::map* map = + static_cast*>(linuxVal); + + ThreadLocalEntry* appVal = (*map)[idx]; + + if (appVal) + delete appVal; + + (*map)[idx] = new ThreadLocalTypedEntry(val); + } + else + { + std::map* map = new std::map(); + + Set0(map); + + (*map)[idx] = new ThreadLocalTypedEntry(val); + } + } + + /** + * Remove value at the given index. + * + * @param idx Index. + */ + static void Remove(int32_t idx); + + /** + * Internal thread-local map clear routine. + * + * @param mapPtr Pointer to map. + */ + static void Clear0(void* mapPtr); + + private: + /** + * Internal get routine. + * + * @param Associated value. + */ + static void* Get0(); + + /** + * Internal set routine. + * + * @param ptr Pointer. + */ + static void Set0(void* ptr); + }; + + /** + * Thread-local instance. Simplifies API avoiding direct index allocations. + */ + template + class IGNITE_IMPORT_EXPORT ThreadLocalInstance + { + public: + /** + * Constructor. + */ + ThreadLocalInstance() : idx(ThreadLocal::NextIndex()) + { + // No-op. + } + + /** + * Destructor. + */ + ~ThreadLocalInstance() + { + Remove(); + } + + /** + * Get value. + * + * @return Value. + */ + T Get() + { + return ThreadLocal::Get(idx); + } + + /** + * Set instance. + * + * @param val Value. + */ + void Set(const T& val) + { + ThreadLocal::Set(idx, val); + } + + /** + * Remove instance. + */ + void Remove() + { + ThreadLocal::Remove(idx); + } + + private: + /** Index. */ + int32_t idx; + }; + + /** + * Cross-platform wrapper for Condition Variable synchronization + * primitive concept. + */ + class ConditionVariable + { + public: + /** + * Constructor. + */ + ConditionVariable() + { + pthread_condattr_t attr; + int err = pthread_condattr_init(&attr); + assert(!err); + IGNITE_UNUSED(err); + + #if !defined(__APPLE__) + err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + assert(!err); + IGNITE_UNUSED(err); + #endif + err = pthread_cond_init(&cond, &attr); + assert(!err); + IGNITE_UNUSED(err); + } + + /** + * Destructor. + */ + ~ConditionVariable() + { + pthread_cond_destroy(&cond); + } + + /** + * Wait for Condition Variable to be notified. + * + * @param cs Critical section in which to wait. + */ + void Wait(CriticalSection& cs) + { + pthread_cond_wait(&cond, &cs.mux); + } + + /** + * Wait for Condition Variable to be notified for specified time. + * + * @param cs Critical section in which to wait. + * @param msTimeout Timeout in milliseconds. + * @return True if the object has been notified and false in case of timeout. + */ + bool WaitFor(CriticalSection& cs, int32_t msTimeout) + { + timespec ts; + int err = clock_gettime(CLOCK_MONOTONIC, &ts); + assert(!err); + + IGNITE_UNUSED(err); + + ts.tv_sec += msTimeout / 1000 + (ts.tv_nsec + (msTimeout % 1000) * 1000000) / 1000000000; + ts.tv_nsec = (ts.tv_nsec + (msTimeout % 1000) * 1000000) % 1000000000; + + int res = pthread_cond_timedwait(&cond, &cs.mux, &ts); + + return res == 0; + } + + /** + * Notify single thread waiting for the condition variable. + */ + void NotifyOne() + { + int err = pthread_cond_signal(&cond); + + assert(!err); + + IGNITE_UNUSED(err); + } + + /** + * Notify all threads that are waiting on the variable. + */ + void NotifyAll() + { + int err = pthread_cond_broadcast(&cond); + + assert(!err); + + IGNITE_UNUSED(err); + } + + private: + IGNITE_NO_COPY_ASSIGNMENT(ConditionVariable); + + /** OS-specific type. */ + pthread_cond_t cond; + }; + + /** + * Manually triggered event. + * Once triggered it stays in passing state until manually reset. + */ + class ManualEvent + { + public: + /** + * Constructs manual event. + * Initial state is untriggered. + */ + ManualEvent() : + cond(), + mutex(), + state(false) + { + pthread_condattr_t attr; + int err = pthread_condattr_init(&attr); + assert(!err); + IGNITE_UNUSED(err); + + #if !defined(__APPLE__) + err = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + assert(!err); + IGNITE_UNUSED(err); + #endif + + err = pthread_cond_init(&cond, &attr); + assert(!err); + IGNITE_UNUSED(err); + + err = pthread_mutex_init(&mutex, NULL); + assert(!err); + IGNITE_UNUSED(err); + } + + /** + * Destructor. + */ + ~ManualEvent() + { + pthread_mutex_destroy(&mutex); + pthread_cond_destroy(&cond); + } + + /** + * Sets event into triggered state. + */ + void Set() + { + int err = pthread_mutex_lock(&mutex); + assert(!err); + IGNITE_UNUSED(err); + + state = true; + + err = pthread_cond_broadcast(&cond); + assert(!err); + IGNITE_UNUSED(err); + + err = pthread_mutex_unlock(&mutex); + assert(!err); + IGNITE_UNUSED(err); + } + + /** + * Resets event into non-triggered state. + */ + void Reset() + { + int err = pthread_mutex_lock(&mutex); + assert(!err); + IGNITE_UNUSED(err); + + state = false; + + err = pthread_mutex_unlock(&mutex); + assert(!err); + IGNITE_UNUSED(err); + } + + /** + * Wait for event to be triggered. + */ + void Wait() + { + int err = pthread_mutex_lock(&mutex); + assert(!err); + IGNITE_UNUSED(err); + + while (!state) + { + err = pthread_cond_wait(&cond, &mutex); + assert(!err); + IGNITE_UNUSED(err); + } + + err = pthread_mutex_unlock(&mutex); + assert(!err); + IGNITE_UNUSED(err); + } + + /** + * Wait for event to be triggered for specified time. + * + * @param msTimeout Timeout in milliseconds. + * @return True if the object has been triggered and false in case of timeout. + */ + bool WaitFor(int32_t msTimeout) + { + int res = 0; + int err = pthread_mutex_lock(&mutex); + assert(!err); + IGNITE_UNUSED(err); + + if (!state) + { + timespec ts; + err = clock_gettime(CLOCK_MONOTONIC, &ts); + assert(!err); + IGNITE_UNUSED(err); + + ts.tv_sec += msTimeout / 1000 + (ts.tv_nsec + (msTimeout % 1000) * 1000000) / 1000000000; + ts.tv_nsec = (ts.tv_nsec + (msTimeout % 1000) * 1000000) % 1000000000; + + res = pthread_cond_timedwait(&cond, &mutex, &ts); + assert(res == 0 || res == ETIMEDOUT); + IGNITE_UNUSED(res); + } + + err = pthread_mutex_unlock(&mutex); + assert(!err); + IGNITE_UNUSED(err); + + return res == 0; + } + + private: + IGNITE_NO_COPY_ASSIGNMENT(ManualEvent); + + /** Condition variable. */ + pthread_cond_t cond; + + /** Mutex. */ + pthread_mutex_t mutex; + + /** State. */ + bool state; + }; + } + } + } +} + +#endif // _IGNITE_ODBC_COMMON_CONCURRENT_OS diff --git a/src/odbc/os/linux/src/common/concurrent_os.cpp b/src/odbc/os/linux/src/common/concurrent_os.cpp new file mode 100644 index 000000000..aa04e55c9 --- /dev/null +++ b/src/odbc/os/linux/src/common/concurrent_os.cpp @@ -0,0 +1,211 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ignite/odbc/common/concurrent_os.h" + +namespace ignite +{ + namespace odbc + { + namespace common + { + namespace concurrent + { + /** Key indicating that the thread is attached. */ + static pthread_key_t tlsKey; + + /** Helper to ensure that attach key is allocated only once. */ + static pthread_once_t tlsKeyInit = PTHREAD_ONCE_INIT; + + /** + * Routine to destroy TLS key. + * + * @param key Key. + */ + void DestroyTlsKey(void* key) { + ThreadLocal::Clear0(key); + } + + /** + * Routine to allocate TLS key. + */ + void AllocateTlsKey() { + pthread_key_create(&tlsKey, DestroyTlsKey); + } + + void Memory::Fence() { + __asm__ volatile ("" ::: "memory"); + } + + CriticalSection::CriticalSection() { + pthread_mutex_init(&mux, NULL); + + Memory::Fence(); + } + + CriticalSection::~CriticalSection() { + Memory::Fence(); + + pthread_mutex_destroy(&mux); + } + + void CriticalSection::Enter() { + Memory::Fence(); + + pthread_mutex_lock(&mux); + } + + void CriticalSection::Leave() { + Memory::Fence(); + + pthread_mutex_unlock(&mux); + } + + ReadWriteLock::ReadWriteLock() : + lock() + { + pthread_rwlock_init(&lock, NULL); + + Memory::Fence(); + } + + ReadWriteLock::~ReadWriteLock() + { + pthread_rwlock_destroy(&lock); + } + + void ReadWriteLock::LockExclusive() + { + pthread_rwlock_wrlock(&lock); + } + + void ReadWriteLock::ReleaseExclusive() + { + pthread_rwlock_unlock(&lock); + } + + void ReadWriteLock::LockShared() + { + pthread_rwlock_rdlock(&lock); + } + + void ReadWriteLock::ReleaseShared() + { + pthread_rwlock_unlock(&lock); + } + + SingleLatch::SingleLatch() + { + pthread_mutex_init(&mux, NULL); + pthread_cond_init(&cond, NULL); + ready = false; + + Memory::Fence(); + } + + SingleLatch::~SingleLatch() + { + Memory::Fence(); + + pthread_cond_destroy(&cond); + pthread_mutex_destroy(&mux); + } + + void SingleLatch::CountDown() + { + pthread_mutex_lock(&mux); + + if (!ready) { + ready = true; + + pthread_cond_broadcast(&cond); + } + + pthread_mutex_unlock(&mux); + + Memory::Fence(); + } + + void SingleLatch::Await() + { + pthread_mutex_lock(&mux); + + while (!ready) + pthread_cond_wait(&cond, &mux); + + pthread_mutex_unlock(&mux); + + Memory::Fence(); + } + + bool Atomics::CompareAndSet32(int32_t* ptr, int32_t expVal, int32_t newVal) + { + return __sync_bool_compare_and_swap(ptr, expVal, newVal); + } + + int32_t Atomics::CompareAndSet32Val(int32_t* ptr, int32_t expVal, int32_t newVal) + { + return __sync_val_compare_and_swap(ptr, expVal, newVal); + } + + int32_t Atomics::IncrementAndGet32(int32_t* ptr) + { + return __sync_fetch_and_add(ptr, 1) + 1; + } + + int32_t Atomics::DecrementAndGet32(int32_t* ptr) + { + return __sync_fetch_and_sub(ptr, 1) - 1; + } + + bool Atomics::CompareAndSet64(int64_t* ptr, int64_t expVal, int64_t newVal) + { + return __sync_bool_compare_and_swap(ptr, expVal, newVal); + } + + int64_t Atomics::CompareAndSet64Val(int64_t* ptr, int64_t expVal, int64_t newVal) + { + return __sync_val_compare_and_swap(ptr, expVal, newVal); + } + + int64_t Atomics::IncrementAndGet64(int64_t* ptr) + { + return __sync_fetch_and_add(ptr, 1) + 1; + } + + int64_t Atomics::DecrementAndGet64(int64_t* ptr) + { + return __sync_fetch_and_sub(ptr, 1) - 1; + } + + void* ThreadLocal::Get0() + { + pthread_once(&tlsKeyInit, AllocateTlsKey); + + return pthread_getspecific(tlsKey); + } + + void ThreadLocal::Set0(void* ptr) + { + pthread_once(&tlsKeyInit, AllocateTlsKey); + + pthread_setspecific(tlsKey, ptr); + } + } + } + } +} diff --git a/src/odbc/os/linux/src/common/platform_utils.cpp b/src/odbc/os/linux/src/common/platform_utils.cpp new file mode 100644 index 000000000..f0076598f --- /dev/null +++ b/src/odbc/os/linux/src/common/platform_utils.cpp @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace ignite +{ + namespace odbc + { + namespace common + { + time_t IgniteTimeGm(const tm& time) + { + tm tmc = time; + + return timegm(&tmc); + } + + time_t IgniteTimeLocal(const tm& time) + { + tm tmc = time; + + return mktime(&tmc); + } + + bool IgniteGmTime(time_t in, tm& out) + { + return gmtime_r(&in, &out) != NULL; + } + + bool IgniteLocalTime(time_t in, tm& out) + { + return localtime_r(&in, &out) == 0; + } + + std::string GetEnv(const std::string& name) + { + static const std::string empty; + + return GetEnv(name, empty); + } + + std::string GetEnv(const std::string& name, const std::string& dflt) + { + char* val0 = std::getenv(name.c_str()); + + if (!val0) + return dflt; + + return std::string(val0); + } + + bool FileExists(const std::string& path) + { + glob_t gs; + + int res = glob(path.c_str(), 0, 0, &gs); + + globfree(&gs); + + return res == 0; + } + + bool IsValidDirectory(const std::string& path) + { + if (path.empty()) + return false; + + struct stat pathStat; + + return stat(path.c_str(), &pathStat) != -1 && S_ISDIR(pathStat.st_mode); + } + + static int rmFiles(const char *pathname, const struct stat*, int, struct FTW*) + { + remove(pathname); + + return 0; + } + + bool DeletePath(const std::string& path) + { + return nftw(path.c_str(), rmFiles, 10, FTW_DEPTH | FTW_MOUNT | FTW_PHYS) == 0; + } + + StdCharOutStream& Fs(StdCharOutStream& ostr) + { + ostr.put('/'); + return ostr; + } + + StdCharOutStream& Dle(StdCharOutStream& ostr) + { + #ifdef __APPLE__ + static const char expansion[] = ".dylib"; + #else + static const char expansion[] = ".so"; + #endif + ostr.write(expansion, sizeof(expansion) - 1); + + return ostr; + } + + IGNITE_IMPORT_EXPORT unsigned GetRandSeed() + { + timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + unsigned res = static_cast(ts.tv_sec); + res ^= static_cast(ts.tv_nsec); + res ^= static_cast(getpid()); + + return res; + } + } + } +} diff --git a/src/odbc/os/win/include/ignite/odbc/common/common.h b/src/odbc/os/win/include/ignite/odbc/common/common.h new file mode 100644 index 000000000..e7cda4b52 --- /dev/null +++ b/src/odbc/os/win/include/ignite/odbc/common/common.h @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef _IGNITE_COMMON_COMMON +#define _IGNITE_COMMON_COMMON + +#define IGNITE_EXPORT __declspec(dllexport) +#define IGNITE_IMPORT __declspec(dllimport) +#define IGNITE_CALL __stdcall + +#define IGNITE_IMPORT_EXPORT IGNITE_EXPORT + +#include + +#define IGNITE_TRACE_ALLOC(addr) \ + std::cout << "ALLOC " << __FILE__ << "(" << __LINE__ << "): 0x" << (void*)addr << std::endl; + +/** + * Common construction to disable copy constructor and assignment for class. + */ +#define IGNITE_NO_COPY_ASSIGNMENT(cls) \ + cls(const cls& src); \ + cls& operator= (const cls& other); + +#if (__cplusplus >= 201103L) +# define IGNITE_NO_THROW noexcept +#else +# define IGNITE_NO_THROW throw() +#endif + +#define IGNITE_UNUSED(x) ((void) x) + +#endif //_IGNITE_COMMON_COMMON \ No newline at end of file diff --git a/src/odbc/os/win/include/ignite/odbc/common/concurrent_os.h b/src/odbc/os/win/include/ignite/odbc/common/concurrent_os.h new file mode 100644 index 000000000..855a995b6 --- /dev/null +++ b/src/odbc/os/win/include/ignite/odbc/common/concurrent_os.h @@ -0,0 +1,610 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_COMMON_CONCURRENT_OS +#define _IGNITE_ODBC_COMMON_CONCURRENT_OS + +#include + +#include +#include + +#include + +#include "ignite/odbc/common/common.h" +namespace ignite +{ + namespace odbc + { + namespace common + { + namespace concurrent + { + /** + * Static class to manage memory visibility semantics. + */ + class IGNITE_IMPORT_EXPORT Memory + { + public: + /** + * Full fence. + */ + static void Fence(); + }; + + /** + * Critical section. + */ + class IGNITE_IMPORT_EXPORT CriticalSection + { + friend class ConditionVariable; + public: + /** + * Constructor. + */ + CriticalSection(); + + /** + * Destructor. + */ + ~CriticalSection(); + + /** + * Enter critical section. + */ + void Enter(); + + /** + * Leave critical section. + */ + void Leave(); + private: + /** Handle. */ + CRITICAL_SECTION hnd; + + IGNITE_NO_COPY_ASSIGNMENT(CriticalSection) + }; + + class IGNITE_IMPORT_EXPORT ReadWriteLock + { + public: + /** + * Constructor. + */ + ReadWriteLock(); + + /** + * Destructor. + */ + ~ReadWriteLock(); + + /** + * Lock in exclusive mode. + */ + void LockExclusive(); + + /** + * Release in exclusive mode. + */ + void ReleaseExclusive(); + + /** + * Lock in shared mode. + */ + void LockShared(); + + /** + * Release in shared mode. + */ + void ReleaseShared(); + + private: + /** Lock. */ + SRWLOCK lock; + + IGNITE_NO_COPY_ASSIGNMENT(ReadWriteLock) + }; + + /** + * Special latch with count = 1. + */ + class IGNITE_IMPORT_EXPORT SingleLatch + { + public: + /** + * Constructor. + */ + SingleLatch(); + + /** + * Destructor. + */ + ~SingleLatch(); + + /** + * Perform the countdown. + */ + void CountDown(); + + /** + * Await the countdown. + */ + void Await(); + private: + /** Handle. */ + HANDLE hnd = CreateEvent(nullptr, TRUE, FALSE, nullptr); + + IGNITE_NO_COPY_ASSIGNMENT(SingleLatch) + }; + + /** + * Primitives for atomic access. + */ + class IGNITE_IMPORT_EXPORT Atomics + { + public: + /** + * Update the 32-bit integer value if it is equal to expected value. + * + * @param ptr Pointer. + * @param expVal Expected value. + * @param newVal New value. + * @return True if update occurred as a result of this call, false otherwise. + */ + static bool CompareAndSet32(int32_t* ptr, int32_t expVal, int32_t newVal); + + /** + * Update the 32-bit integer value if it is equal to expected value. + * + * @param ptr Pointer. + * @param expVal Expected value. + * @param newVal New value. + * @return Value which were observed during CAS attempt. + */ + static int32_t CompareAndSet32Val(int32_t* ptr, int32_t expVal, int32_t newVal); + + /** + * Increment 32-bit integer and return new value. + * + * @param ptr Pointer. + * @return Value after increment. + */ + static int32_t IncrementAndGet32(int32_t* ptr); + + /** + * Decrement 32-bit integer and return new value. + * + * @param ptr Pointer. + * @return Value after decrement. + */ + static int32_t DecrementAndGet32(int32_t* ptr); + + /** + * Update the 64-bit integer value if it is equal to expected value. + * + * @param ptr Pointer. + * @param expVal Expected value. + * @param newVal New value. + * @return True if update occurred as a result of this call, false otherwise. + */ + static bool CompareAndSet64(int64_t* ptr, int64_t expVal, int64_t newVal); + + /** + * Update the 64-bit integer value if it is equal to expected value. + * + * @param ptr Pointer. + * @param expVal Expected value. + * @param newVal New value. + * @return Value which were observed during CAS attempt. + */ + static int64_t CompareAndSet64Val(int64_t* ptr, int64_t expVal, int64_t newVal); + + /** + * Increment 64-bit integer and return new value. + * + * @param ptr Pointer. + * @return Value after increment. + */ + static int64_t IncrementAndGet64(int64_t* ptr); + + /** + * Decrement 64-bit integer and return new value. + * + * @param ptr Pointer. + * @return Value after decrement. + */ + static int64_t DecrementAndGet64(int64_t* ptr); + }; + + /** + * Thread-local entry. + */ + class IGNITE_IMPORT_EXPORT ThreadLocalEntry + { + public: + /** + * Virtual destructor to allow for correct typed entries cleanup. + */ + virtual ~ThreadLocalEntry() + { + // No-op. + } + }; + + /** + * Typed thread-local entry. + */ + template + class IGNITE_IMPORT_EXPORT ThreadLocalTypedEntry : public ThreadLocalEntry + { + public: + /** + * Constructor. + * + * @param val Value. + */ + ThreadLocalTypedEntry(T val) : val(val) + { + // No-op. + } + + ~ThreadLocalTypedEntry() + { + // No-op. + } + + /** + * Get value. + * + * @return Value. + */ + T Get() + { + return val; + } + private: + /** Value. */ + T val; + }; + + /** + * Thread-local abstraction. + */ + class IGNITE_IMPORT_EXPORT ThreadLocal + { + public: + /** + * Allocate thread-local index. Invoked once on DLL process attach. + * + * @return True if allocation was successful. + */ + static bool OnProcessAttach(); + + /** + * Release thread-local entry. Invoked on DLL thread detach. + */ + static void OnThreadDetach(); + + /** + * Release thread-local index. Invoked once on DLL process detach. + */ + static void OnProcessDetach(); + + /** + * Get next available index to be used in thread-local storage. + * + * @return Index. + */ + static int32_t NextIndex(); + + /** + * Get value by index. + * + * @param idx Index. + * @return Value associated with the index or NULL. + */ + template + static T Get(int32_t idx) + { + void* winVal = Get0(); + + if (winVal) + { + std::map* map = + static_cast*>(winVal); + + ThreadLocalTypedEntry* entry = static_cast*>((*map)[idx]); + + if (entry) + return entry->Get(); + } + + return T(); + } + + /** + * Set value at the given index. + * + * @param idx Index. + * @param val Value to be associated with the index. + */ + template + static void Set(int32_t idx, const T& val) + { + void* winVal = Get0(); + + if (winVal) + { + std::map* map = + static_cast*>(winVal); + + ThreadLocalEntry* appVal = (*map)[idx]; + + if (appVal) + delete appVal; + + (*map)[idx] = new ThreadLocalTypedEntry(val); + } + else + { + std::map* map = new std::map(); + + Set0(map); + + (*map)[idx] = new ThreadLocalTypedEntry(val); + } + } + + /** + * Remove value at the given index. + * + * @param idx Index. + */ + static void Remove(int32_t idx); + + private: + /** + * Internal get routine. + * + * @param Associated value. + */ + static void* Get0(); + + /** + * Internal set routine. + * + * @param ptr Pointer. + */ + static void Set0(void* ptr); + + /** + * Internal thread-local map clear routine. + * + * @param mapPtr Pointer to map. + */ + static void Clear0(void* mapPtr); + }; + + /** + * Thread-local instance. Simplifies API avoiding direct index allocations. + */ + template + class IGNITE_IMPORT_EXPORT ThreadLocalInstance + { + public: + /** + * Constructor. + */ + ThreadLocalInstance() : idx(ThreadLocal::NextIndex()) + { + // No-op. + } + + /** + * Destructor. + */ + ~ThreadLocalInstance() + { + Remove(); + } + + /** + * Get value. + * + * @return Value. + */ + T Get() + { + return ThreadLocal::Get(idx); + } + + /** + * Set instance. + * + * @param val Value. + */ + void Set(const T& val) + { + ThreadLocal::Set(idx, val); + } + + /** + * Remove instance. + */ + void Remove() + { + ThreadLocal::Remove(idx); + } + + private: + /** Index. */ + int32_t idx; + }; + + /** + * Cross-platform wrapper for Condition Variable synchronization + * primitive concept. + */ + class ConditionVariable + { + public: + /** + * Constructor. + */ + ConditionVariable() + { + InitializeConditionVariable(&cond); + } + + /** + * Destructor. + */ + ~ConditionVariable() + { + // No-op. + } + + /** + * Wait for Condition Variable to be notified. + * + * @param cs Critical section in which to wait. + */ + void Wait(CriticalSection& cs) + { + SleepConditionVariableCS(&cond, &cs.hnd, INFINITE); + } + + /** + * Wait for Condition Variable to be notified for specified time. + * + * @param cs Critical section in which to wait. + * @param msTimeout Timeout in milliseconds. + * @return True if the object has been notified and false in case of timeout. + */ + bool WaitFor(CriticalSection& cs, int32_t msTimeout) + { + BOOL notified = SleepConditionVariableCS(&cond, &cs.hnd, msTimeout); + + return notified != FALSE; + } + + /** + * Notify single thread waiting for the condition variable. + */ + void NotifyOne() + { + WakeConditionVariable(&cond); + } + + /** + * Notify all threads that are waiting on the variable. + */ + void NotifyAll() + { + WakeAllConditionVariable(&cond); + } + + private: + IGNITE_NO_COPY_ASSIGNMENT(ConditionVariable); + + /** OS-specific type. */ + CONDITION_VARIABLE cond; + }; + + /** + * Manually triggered event. + * Once triggered it stays in passing state until manually reset. + */ + class ManualEvent + { + public: + /** + * Constructs manual event. + * Initial state is untriggered. + */ + ManualEvent() + { + handle = CreateEvent(NULL, TRUE, FALSE, NULL); + + assert(handle != NULL); + } + + /** + * Destructor. + */ + ~ManualEvent() + { + CloseHandle(handle); + } + + /** + * Sets event into triggered state. + */ + void Set() + { + BOOL success = SetEvent(handle); + + assert(success); + } + + /** + * Resets event into non-triggered state. + */ + void Reset() + { + BOOL success = ResetEvent(handle); + + assert(success); + } + + /** + * Wait for event to be triggered. + */ + void Wait() + { + DWORD res = WaitForSingleObject(handle, INFINITE); + + assert(res == WAIT_OBJECT_0); + } + + /** + * Wait for event to be triggered for specified time. + * + * @param msTimeout Timeout in milliseconds. + * @return True if the object has been triggered and false in case of timeout. + */ + bool WaitFor(int32_t msTimeout) + { + DWORD res = WaitForSingleObject(handle, static_cast(msTimeout)); + + assert(res == WAIT_OBJECT_0 || res == WAIT_TIMEOUT); + + return res == WAIT_OBJECT_0; + } + + private: + IGNITE_NO_COPY_ASSIGNMENT(ManualEvent); + + /** Event handle. */ + HANDLE handle; + }; + } + } + } +} + +#endif //_IGNITE_ODBC_COMMON_CONCURRENT_OS diff --git a/src/odbc/os/win/src/common/concurrent_os.cpp b/src/odbc/os/win/src/common/concurrent_os.cpp new file mode 100644 index 000000000..71f5587db --- /dev/null +++ b/src/odbc/os/win/src/common/concurrent_os.cpp @@ -0,0 +1,208 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ignite/odbc/common/concurrent_os.h" + +#pragma intrinsic(_InterlockedCompareExchange64) + +namespace ignite +{ + namespace odbc + { + namespace common + { + namespace concurrent + { + /** Thread-local index for Windows. */ + DWORD winTlsIdx; + + void Memory::Fence() { + MemoryBarrier(); + } + + CriticalSection::CriticalSection() : + hnd() + { + InitializeCriticalSection(&hnd); + + Memory::Fence(); + } + + CriticalSection::~CriticalSection() = default; + + void CriticalSection::Enter() + { + Memory::Fence(); + + EnterCriticalSection(&hnd); + } + + void CriticalSection::Leave() + { + Memory::Fence(); + + LeaveCriticalSection(&hnd); + } + + ReadWriteLock::ReadWriteLock() : + lock() + { + InitializeSRWLock(&lock); + + Memory::Fence(); + } + + ReadWriteLock::~ReadWriteLock() = default; + + void ReadWriteLock::LockExclusive() + { + AcquireSRWLockExclusive(&lock); + } + + void ReadWriteLock::ReleaseExclusive() + { + ReleaseSRWLockExclusive(&lock); + } + + void ReadWriteLock::LockShared() + { + AcquireSRWLockShared(&lock); + } + + void ReadWriteLock::ReleaseShared() + { + ReleaseSRWLockShared(&lock); + } + + SingleLatch::SingleLatch() + { + Memory::Fence(); + } + + SingleLatch::~SingleLatch() + { + Memory::Fence(); + + CloseHandle(hnd); + } + + void SingleLatch::CountDown() + { + SetEvent(hnd); + } + + void SingleLatch::Await() + { + WaitForSingleObject(hnd, INFINITE); + } + + bool Atomics::CompareAndSet32(int32_t* ptr, int32_t expVal, int32_t newVal) + { + return CompareAndSet32Val(ptr, expVal, newVal) == expVal; + } + + int32_t Atomics::CompareAndSet32Val(int32_t* ptr, int32_t expVal, int32_t newVal) + { + return InterlockedCompareExchange(reinterpret_cast(ptr), newVal, expVal); + } + + int32_t Atomics::IncrementAndGet32(int32_t* ptr) + { + return InterlockedIncrement(reinterpret_cast(ptr)); + } + + int32_t Atomics::DecrementAndGet32(int32_t* ptr) + { + return InterlockedDecrement(reinterpret_cast(ptr)); + } + + bool Atomics::CompareAndSet64(int64_t* ptr, int64_t expVal, int64_t newVal) + { + return CompareAndSet64Val(ptr, expVal, newVal) == expVal; + } + + int64_t Atomics::CompareAndSet64Val(int64_t* ptr, int64_t expVal, int64_t newVal) + { + return _InterlockedCompareExchange64(ptr, newVal, expVal); + } + + int64_t Atomics::IncrementAndGet64(int64_t* ptr) + { + #ifdef _WIN64 + return InterlockedIncrement64(ptr); + #else + while (true) + { + int64_t expVal = *ptr; + int64_t newVal = expVal + 1; + + if (CompareAndSet64(ptr, expVal, newVal)) + return newVal; + } + #endif + } + + int64_t Atomics::DecrementAndGet64(int64_t* ptr) + { + #ifdef _WIN64 + return InterlockedDecrement64(ptr); + #else + while (true) + { + int64_t expVal = *ptr; + int64_t newVal = expVal - 1; + + if (CompareAndSet64(ptr, expVal, newVal)) + return newVal; + } + #endif + } + + bool ThreadLocal::OnProcessAttach() + { + return (winTlsIdx = TlsAlloc()) != TLS_OUT_OF_INDEXES; + } + + void ThreadLocal::OnThreadDetach() + { + if (winTlsIdx != TLS_OUT_OF_INDEXES) + { + void* mapPtr = Get0(); + + Clear0(mapPtr); + } + } + + void ThreadLocal::OnProcessDetach() + { + if (winTlsIdx != TLS_OUT_OF_INDEXES) + TlsFree(winTlsIdx); + } + + void* ThreadLocal::Get0() + { + return TlsGetValue(winTlsIdx); + } + + void ThreadLocal::Set0(void* ptr) + { + TlsSetValue(winTlsIdx, ptr); + } + } + } + } +} diff --git a/src/odbc/os/win/src/common/platform_utils.cpp b/src/odbc/os/win/src/common/platform_utils.cpp new file mode 100644 index 000000000..35261fa0d --- /dev/null +++ b/src/odbc/os/win/src/common/platform_utils.cpp @@ -0,0 +1,140 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include + +namespace ignite { + namespace odbc + { + namespace common + { + time_t IgniteTimeGm(const tm& time) + { + tm tmc = time; + + return _mkgmtime(&tmc); + } + + time_t IgniteTimeLocal(const tm& time) + { + tm tmc = time; + + return mktime(&tmc); + } + + bool IgniteGmTime(time_t in, tm& out) + { + return gmtime_s(&out, &in) == 0; + } + + bool IgniteLocalTime(time_t in, tm& out) + { + return localtime_s(&out, &in) == 0; + } + + std::string GetEnv(const std::string& name) + { + static const std::string empty; + + return GetEnv(name, empty); + } + + std::string GetEnv(const std::string& name, const std::string& dflt) + { + char res[32767]; + + DWORD envRes = GetEnvironmentVariableA(name.c_str(), res, sizeof(res) / sizeof(res[0])); + + if (envRes == 0 || envRes > sizeof(res)) + return dflt; + + return std::string(res, static_cast(envRes)); + } + + bool FileExists(const std::string& path) + { + WIN32_FIND_DATAA findres; + + HANDLE hnd = FindFirstFileA(path.c_str(), &findres); + + if (hnd == INVALID_HANDLE_VALUE) + return false; + + FindClose(hnd); + + return true; + } + + bool IsValidDirectory(const std::string& path) + { + if (path.empty()) + return false; + + DWORD attrs = GetFileAttributesA(path.c_str()); + + return attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0; + } + + bool DeletePath(const std::string& path) + { + std::vector path0(path.begin(), path.end()); + path0.push_back('\0'); + path0.push_back('\0'); + + SHFILEOPSTRUCT fileop; + fileop.hwnd = nullptr; + fileop.wFunc = FO_DELETE; + fileop.pFrom = &path0[0]; + fileop.pTo = nullptr; + fileop.fFlags = FOF_NOCONFIRMATION | FOF_SILENT; + + fileop.fAnyOperationsAborted = FALSE; + fileop.lpszProgressTitle = nullptr; + fileop.hNameMappings = nullptr; + + int ret = SHFileOperation(&fileop); + + return ret == 0; + } + + StdCharOutStream& Fs(StdCharOutStream& ostr) + { + ostr.put('\\'); + return ostr; + } + + StdCharOutStream& Dle(StdCharOutStream& ostr) + { + static const char expansion[] = ".dll"; + + ostr.write(expansion, sizeof(expansion) - 1); + + return ostr; + } + + IGNITE_IMPORT_EXPORT unsigned GetRandSeed() + { + return static_cast(GetTickCount64() ^ GetCurrentProcessId()); + } + } + } +} diff --git a/src/odbc/os/win/src/system/ui/window.cpp b/src/odbc/os/win/src/system/ui/window.cpp index 02d62e2d8..8512bda8a 100644 --- a/src/odbc/os/win/src/system/ui/window.cpp +++ b/src/odbc/os/win/src/system/ui/window.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include "ignite/odbc/system/ui/window.h" @@ -58,7 +58,7 @@ namespace ignite title(), handle(handle), created(false), - parent(0) + parent(nullptr) { // No-op. } @@ -88,7 +88,7 @@ namespace ignite posY, width, height, - parent ? parent->GetHandle() : NULL, + parent ? parent->GetHandle() : nullptr, reinterpret_cast(static_cast(id)), GetHInstance(), this @@ -125,7 +125,7 @@ namespace ignite if (handle) DestroyWindow(handle); - handle = NULL; + handle = nullptr; } void Window::GetText(std::string& text) const diff --git a/src/odbc/src/app/application_data_buffer.cpp b/src/odbc/src/app/application_data_buffer.cpp index 2942defc8..f4977bb09 100644 --- a/src/odbc/src/app/application_data_buffer.cpp +++ b/src/odbc/src/app/application_data_buffer.cpp @@ -19,7 +19,7 @@ #include #include -#include "ignite/common/bits.h" +#include "ignite/odbc/common/bits.h" #include "ignite/impl/binary/binary_utils.h" diff --git a/src/odbc/src/common/big_integer.cpp b/src/odbc/src/common/big_integer.cpp new file mode 100644 index 000000000..3114a452f --- /dev/null +++ b/src/odbc/src/common/big_integer.cpp @@ -0,0 +1,866 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ignite/odbc/ignite_error.h" +#include "ignite/odbc/common/bits.h" +#include "ignite/odbc/common/big_integer.h" + +namespace ignite +{ + namespace odbc + { + namespace common + { + BigInteger::BigInteger() : + sign(1), + mag() + { + // No-op. + } + + BigInteger::BigInteger(int64_t val) : + sign(1), + mag() + { + AssignInt64(val); + } + + BigInteger::BigInteger(const char* val, int32_t len) : + sign(1), + mag() + { + AssignString(val, len); + } + + BigInteger::BigInteger(const BigInteger& other) : + sign(other.sign), + mag(other.mag) + { + // No-op. + } + + BigInteger::BigInteger(const int8_t* val, int32_t len, int32_t sign, bool bigEndian) : + sign(sign), + mag() + { + assert(val != 0); + assert(len >= 0); + assert(sign == 1 || sign == 0 || sign == -1); + + if (bigEndian) + { + int32_t firstNonZero = 0; + while (firstNonZero < len && val[firstNonZero] == 0) + ++firstNonZero; + + if (firstNonZero == len) + { + AssignInt64(0); + + return; + } + + int32_t intLength = (len - firstNonZero + 3) / 4; + + mag.Resize(intLength); + + int32_t b = len - 1; + + for (int32_t i = 0; i < intLength - 1; ++i) + { + mag[i] = (val[b] & 0xFFUL) + | ((val[b - 1] & 0xFFUL) << 8) + | ((val[b - 2] & 0xFFUL) << 16) + | ((val[b - 3] & 0xFFUL) << 24); + + b -= 4; + } + + int32_t bytesRemaining = b - firstNonZero + 1; + + assert(bytesRemaining > 0 && bytesRemaining <= 4); + + switch (bytesRemaining) + { + case 4: + mag[intLength - 1] |= (val[b - 3] & 0xFF) << 24; + // Fall-through. + + case 3: + mag[intLength - 1] |= (val[b - 2] & 0xFF) << 16; + // Fall-through. + + case 2: + mag[intLength - 1] |= (val[b - 1] & 0xFF) << 8; + // Fall-through. + + case 1: + mag[intLength - 1] |= val[b] & 0xFF; + // Fall-through. + + default: + break; + } + } + else + { + int32_t firstNonZero = len - 1; + + while (firstNonZero >= 0 && val[firstNonZero] == 0) + --firstNonZero; + + if (firstNonZero == -1) + { + AssignInt64(0); + + return; + } + + int32_t intLength = (firstNonZero + 4) / 4; + + mag.Resize(intLength); + + int32_t b = 0; + + for (int32_t i = 0; i < intLength - 1; ++i) + { + mag[i] = (val[b] & 0xFFUL) + | ((val[b + 1] & 0xFFUL) << 8) + | ((val[b + 2] & 0xFFUL) << 16) + | ((val[b + 3] & 0xFFUL) << 24); + + b += 4; + } + + int32_t bytesRemaining = firstNonZero - b + 1; + + assert(bytesRemaining > 0 && bytesRemaining <= 4); + + switch (bytesRemaining) + { + case 4: + mag[intLength - 1] |= (val[b + 3] & 0xFF) << 24; + // Fall-through. + + case 3: + mag[intLength - 1] |= (val[b + 2] & 0xFF) << 16; + // Fall-through. + + case 2: + mag[intLength - 1] |= (val[b + 1] & 0xFF) << 8; + // Fall-through. + + case 1: + mag[intLength - 1] |= val[b] & 0xFF; + // Fall-through. + + default: + break; + } + } + } + + BigInteger::BigInteger(MagArray &mag, int8_t sign) : + sign(sign), + mag() + { + this->mag.Swap(mag); + } + + BigInteger& BigInteger::operator=(const BigInteger& other) + { + Assign(other); + + return *this; + } + + void BigInteger::Assign(const BigInteger& val) + { + if (this != &val) + { + sign = val.sign; + mag = val.mag; + } + } + + void BigInteger::AssignInt64(int64_t val) + { + if (val < 0) + { + AssignUint64(static_cast(-val)); + + sign = -1; + } + else + AssignUint64(static_cast(val)); + } + + void BigInteger::AssignString(const char* val, int32_t len) + { + std::stringstream converter; + + converter.write(val, len); + + converter >> *this; + } + + void BigInteger::AssignUint64(uint64_t val) + { + sign = 1; + + if (val == 0) + { + mag.Clear(); + + return; + } + + uint32_t highWord = static_cast(val >> 32); + + if (highWord == 0) + mag.Resize(1); + else + { + mag.Resize(2); + mag[1] = highWord; + } + + mag[0] = static_cast(val); + } + + int8_t BigInteger::GetSign() const + { + return sign; + } + + void BigInteger::Swap(BigInteger& other) + { + using std::swap; + + swap(sign, other.sign); + mag.Swap(other.mag); + } + + const BigInteger::MagArray& BigInteger::GetMagnitude() const + { + return mag; + } + + uint32_t BigInteger::GetBitLength() const + { + if (mag.IsEmpty()) + return 0; + + int32_t res = bits::BitLengthU32(mag[mag.GetSize() - 1]); + + if (mag.GetSize() > 1) + res += (mag.GetSize() - 1) * 32; + + return res; + } + + int32_t BigInteger::GetPrecision() const + { + // See http://graphics.stanford.edu/~seander/bithacks.html + // for the details on the algorithm. + + if (mag.GetSize() == 0) + return 1; + + int32_t r = static_cast((( + static_cast(GetBitLength()) + 1) * 646456993) >> 31); + + BigInteger prec; + BigInteger::GetPowerOfTen(r, prec); + + return Compare(prec, true) < 0 ? r : r + 1; + } + + void BigInteger::MagnitudeToBytes(common::FixedSizeArray& buffer) const + { + int32_t bytesNum = static_cast((GetBitLength() + 7) / 8); + + if (bytesNum == 0) + { + buffer.Reset(1); + + return; + } + + buffer.Reset(bytesNum); + + int32_t i; + for (i = 0; i < mag.GetSize() - 1; ++i) + { + int32_t j = bytesNum - 1 - 4 * i; + + buffer[j] = static_cast(mag[i]); + buffer[j - 1] = static_cast(mag[i] >> 8); + buffer[j - 2] = static_cast(mag[i] >> 16); + buffer[j - 3] = static_cast(mag[i] >> 24); + } + + int32_t bytesRemaining = bytesNum - 4 * i; + + assert(bytesRemaining >= 0 && bytesRemaining <= 4); + + i = 0; + switch (bytesRemaining) + { + case 4: + buffer[i++] |= static_cast(mag[mag.GetSize() - 1] >> 24); + // Fall-through. + + case 3: + buffer[i++] |= static_cast(mag[mag.GetSize() - 1] >> 16); + // Fall-through. + + case 2: + buffer[i++] |= static_cast(mag[mag.GetSize() - 1] >> 8); + // Fall-through. + + case 1: + buffer[i++] |= static_cast(mag[mag.GetSize() - 1]); + // Fall-through. + + default: + break; + } + } + + void BigInteger::Pow(int32_t exp) + { + if (exp < 0) + { + AssignInt64(0); + + return; + } + + uint32_t bitsLen = GetBitLength(); + + if (!bitsLen) + return; + + if (bitsLen == 1) + { + if ((exp % 2 == 0) && sign < 0) + sign = -sign; + + return; + } + + BigInteger multiplicant(*this); + AssignInt64(1); + + int32_t mutExp = exp; + while (mutExp) + { + if (mutExp & 1) + Multiply(multiplicant, *this); + + mutExp >>= 1; + + if (mutExp) + multiplicant.Multiply(multiplicant, multiplicant); + } + } + + void BigInteger::Multiply(const BigInteger& other, BigInteger& res) const + { + MagArray resMag(mag.GetSize() + other.mag.GetSize()); + + resMag.Resize(mag.GetSize() + other.mag.GetSize()); + + for (int32_t i = 0; i < other.mag.GetSize(); ++i) + { + uint32_t carry = 0; + + for (int32_t j = 0; j < mag.GetSize(); ++j) + { + uint64_t product = static_cast(mag[j]) * other.mag[i] + + + resMag[i + j] + carry; + + resMag[i + j] = static_cast(product); + carry = static_cast(product >> 32); + } + + resMag[i + mag.GetSize()] = carry; + } + + res.mag.Swap(resMag); + res.sign = sign * other.sign; + + res.Normalize(); + } + + /** + * Shift magnitude left by the specified number of bits. + * + * @param in Input magnitude. + * @param len Magnitude length. + * @param out Output magnitude. Should be not shorter than the input + * magnitude. + * @param n Number of bits to shift to. + */ + void ShiftLeft(const uint32_t* in, int32_t len, uint32_t* out, unsigned n) + { + assert(n < 32); + + if (n == 0) + { + std::copy(in, in + len, out); + + return; + } + + for (int32_t i = len - 1; i > 0; --i) + out[i] = (in[i] << n) | (in[i - 1] >> (32 - n)); + + out[0] = in[0] << n; + } + + /** + * Shift magnitude right by the specified number of bits. + * + * @param in Input magnitude. + * @param len Magnitude length. + * @param out Output magnitude. Should be not shorter than the input + * magnitude. + * @param n Number of bits to shift to. + */ + void ShiftRight(const uint32_t* in, int32_t len, uint32_t* out, unsigned n) + { + assert(n < 32); + + if (n == 0) + { + std::copy(in, in + len, out); + + return; + } + + for (int32_t i = 0; i < len - 1; ++i) + out[i] = (in[i] >> n) | (in[i + 1] << (32 - n)); + + out[len - 1] = in[len - 1] >> n; + } + + /** + * Part of the division algorithm. Computes q - (a * x). + * + * @param q Minuend. + * @param a Multipliplier of the subtrahend. + * @param alen Length of the a. + * @param x Multipliplicand of the subtrahend. + * @return Carry. + */ + uint32_t MultiplyAndSubstruct(uint32_t* q, const uint32_t* a, int32_t alen, uint32_t x) + { + uint64_t carry = 0; + + for (int32_t i = 0; i < alen; ++i) + { + uint64_t product = a[i] * static_cast(x); + int64_t difference = q[i] - carry - (product & 0xFFFFFFFF); + + q[i] = static_cast(difference); + + // This will add one if difference is negative. + carry = (product >> 32) - (difference >> 32); + } + + return static_cast(carry); + } + + /** + * Add two magnitude arrays and return carry. + * + * @param res First addend. Result is placed here. Length of this addend + * should be equal or greater than len. + * @param addend Second addend. + * @param len Length of the second addend. + * @return Carry. + */ + uint32_t Add(uint32_t* res, const uint32_t* addend, int32_t len) + { + uint64_t carry = 0; + + for (int32_t i = 0; i < len; ++i) + { + uint64_t sum = static_cast(res[i]) + addend[i] + carry; + res[i] = static_cast(sum); + carry = sum >> 32; + } + + return static_cast(carry); + } + + /** + * Add single number to a magnitude array and return carry. + * + * @param res First addend. Result is placed here. Length of this addend + * should be equal or greater than len. + * @param len Length of the First addend. + * @param addend Second addend. + * @return Carry. + */ + uint32_t Add(uint32_t* res, int32_t len, uint32_t addend) + { + uint64_t carry = addend; + + for (int32_t i = 0; (i < len) && carry; ++i) + { + uint64_t sum = static_cast(res[i]) + carry; + res[i] = static_cast(sum); + carry = sum >> 32; + } + + return static_cast(carry); + } + + void BigInteger::Divide(const BigInteger& divisor, BigInteger& res) const + { + Divide(divisor, res, 0); + } + + void BigInteger::Divide(const BigInteger& divisor, BigInteger& res, BigInteger& rem) const + { + Divide(divisor, res, &rem); + } + + void BigInteger::Add(const uint32_t* addend, int32_t len) + { + if (mag.GetSize() < len) + { + mag.Reserve(len + 1); + + mag.Resize(len); + } + else + mag.Reserve(mag.GetSize() + 1); + + uint32_t carry = common::Add(mag.GetData(), addend, len); + + if (carry) + { + carry = common::Add(mag.GetData() + len, mag.GetSize() - len, carry); + + if (carry) + mag.PushBack(carry); + } + } + + void BigInteger::Add(uint64_t x) + { + if (x == 0) + return; + + if (IsZero()) + { + AssignUint64(x); + + return; + } + + uint32_t val[2]; + + val[0] = static_cast(x); + val[1] = static_cast(x >> 32); + + Add(val, val[1] ? 2 : 1); + } + + int32_t BigInteger::Compare(const BigInteger& other, bool ignoreSign) const + { + // What we should return if magnitude is greater. + int32_t mgt = 1; + + if (!ignoreSign) + { + if (sign != other.sign) + return sign > other.sign ? 1 : -1; + else + mgt = sign; + } + + if (mag.GetSize() != other.mag.GetSize()) + return mag.GetSize() > other.mag.GetSize() ? mgt : -mgt; + + for (int32_t i = mag.GetSize() - 1; i >= 0; --i) + { + if (mag[i] == other.mag[i]) + continue; + else if (mag[i] > other.mag[i]) + return mgt; + else + return -mgt; + } + + return 0; + } + + int64_t BigInteger::ToInt64() const + { + return (static_cast(GetMagInt(1)) << 32) | GetMagInt(0); + } + + void BigInteger::GetPowerOfTen(int32_t pow, BigInteger& res) + { + using namespace common; + + assert(pow >= 0); + + if (pow < bits::UINT64_MAX_PRECISION) + { + res.AssignUint64(bits::TenPowerU64(pow)); + + return; + } + + res.AssignInt64(10); + res.Pow(pow); + } + + uint32_t BigInteger::GetMagInt(int32_t n) const + { + assert(n >= 0); + + if (n >= mag.GetSize()) + return sign > 0 ? 0 : -1; + + return sign * mag[n]; + } + + void BigInteger::Divide(const BigInteger& divisor, BigInteger& res, BigInteger* rem) const + { + // Can't divide by zero. + if (divisor.mag.IsEmpty()) + throw IgniteError(IgniteError::IGNITE_ERR_ILLEGAL_ARGUMENT, "Division by zero."); + + int32_t compRes = Compare(divisor, true); + + int8_t resSign = sign * divisor.sign; + + // The same magnitude. Result is [-]1 and remainder is zero. + if (compRes == 0) + { + res.AssignInt64(resSign); + + if (rem) + rem->AssignInt64(0); + + return; + } + + // Divisor is greater than this. Result is 0 and remainder is this. + if (compRes == -1) + { + // Order is important here! Copy to rem first to handle the case + // when &res == this. + if (rem) + rem->Assign(*this); + + res.AssignInt64(0); + + return; + } + + // If divisor is [-]1 result is [-]this and remainder is zero. + if (divisor.GetBitLength() == 1) + { + // Once again: order is important. + res.Assign(*this); + res.sign = sign * divisor.sign; + + if (rem) + rem->AssignInt64(0); + + return; + } + + // Trivial case. + if (mag.GetSize() <= 2) + { + uint64_t u = mag[0]; + uint64_t v = divisor.mag[0]; + + if (mag.GetSize() == 2) + u |= static_cast(mag[1]) << 32; + + if (divisor.mag.GetSize() == 2) + v |= static_cast(divisor.mag[1]) << 32; + + // Divisor can not be 1, or 0. + assert(v > 1); + + // It should also be less than dividend. + assert(v < u); + + // (u / v) is always fits into int64_t because abs(v) >= 2. + res.AssignInt64(resSign * static_cast(u / v)); + + // (u % v) is always fits into int64_t because (u > v) -> + // (u % v) < (u / 2). + if (rem) + rem->AssignInt64(resSign * static_cast(u % v)); + + return; + } + + // Using Knuth division algorithm D for common case. + + // Short aliases. + const MagArray& u = mag; + const MagArray& v = divisor.mag; + MagArray& q = res.mag; + int32_t ulen = u.GetSize(); + int32_t vlen = v.GetSize(); + + // First we need to normilize divisor. + MagArray nv; + nv.Resize(v.GetSize()); + + int32_t shift = bits::NumberOfLeadingZerosU32(v.Back()); + ShiftLeft(v.GetData(), vlen, nv.GetData(), shift); + + // Divisor is normilized. Now we need to normilize divident. + MagArray nu; + + // First find out what is the size of it. + if (bits::NumberOfLeadingZerosU32(u.Back()) >= shift) + { + // Everything is the same as with divisor. Just add leading zero. + nu.Resize(ulen + 1); + + ShiftLeft(u.GetData(), ulen, nu.GetData(), shift); + + assert((static_cast(u.Back()) >> (32 - shift)) == 0); + } + else + { + // We need one more byte here. Also adding leading zero. + nu.Resize(ulen + 2); + + ShiftLeft(u.GetData(), ulen, nu.GetData(), shift); + + nu[ulen] = u[ulen - 1] >> (32 - shift); + + assert(nu[ulen] != 0); + } + + assert(nu.Back() == 0); + + // Resizing resulting array. + q.Resize(ulen - vlen + 1); + + // Main loop + for (int32_t i = ulen - vlen; i >= 0; --i) + { + uint64_t base = bits::MakeU64(nu[i + vlen], nu[i + vlen - 1]); + + uint64_t qhat = base / nv[vlen - 1]; // Estimated quotient. + uint64_t rhat = base % nv[vlen - 1]; // A remainder. + + // Adjusting result if needed. + while (qhat > UINT32_MAX || + ((qhat * nv[vlen - 2]) > ((UINT32_MAX + static_cast(1)) * rhat + nu[i + vlen - 2]))) + { + --qhat; + rhat += nv[vlen - 1]; + + if (rhat > UINT32_MAX) + break; + } + + uint32_t qhat32 = static_cast(qhat); + + // Multiply and subtract. + uint32_t carry = MultiplyAndSubstruct(nu.GetData() + i, nv.GetData(), vlen, qhat32); + + int64_t difference = nu[i + vlen] - carry; + + nu[i + vlen] = static_cast(difference); + + if (difference < 0) + { + --qhat32; + carry = common::Add(nu.GetData() + i, nv.GetData(), vlen); + + assert(carry == 0); + } + + q[i] = qhat32; + } + + res.sign = resSign; + res.Normalize(); + + // If remainder is needed unnormolize it. + if (rem) + { + rem->sign = resSign; + rem->mag.Resize(vlen); + + ShiftRight(nu.GetData(), rem->mag.GetSize(), rem->mag.GetData(), shift); + + rem->Normalize(); + } + } + + void BigInteger::Normalize() + { + int32_t lastNonZero = mag.GetSize() - 1; + while (lastNonZero >= 0 && mag[lastNonZero] == 0) + --lastNonZero; + + mag.Resize(lastNonZero + 1); + } + + bool operator==(const BigInteger& val1, const BigInteger& val2) + { + return val1.Compare(val2) == 0; + } + + bool operator!=(const BigInteger& val1, const BigInteger& val2) + { + return val1.Compare(val2) != 0; + } + + bool operator<(const BigInteger& val1, const BigInteger& val2) + { + return val1.Compare(val2) < 0; + } + + bool operator<=(const BigInteger& val1, const BigInteger& val2) + { + return val1.Compare(val2) <= 0; + } + + bool operator>(const BigInteger& val1, const BigInteger& val2) + { + return val1.Compare(val2) > 0; + } + + bool operator>=(const BigInteger& val1, const BigInteger& val2) + { + return val1.Compare(val2) >= 0; + } + } + } +} + diff --git a/src/odbc/src/common/bits.cpp b/src/odbc/src/common/bits.cpp new file mode 100644 index 000000000..a5c922a8b --- /dev/null +++ b/src/odbc/src/common/bits.cpp @@ -0,0 +1,236 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "ignite/odbc/common/bits.h" + +namespace ignite +{ + namespace odbc + { + namespace common + { + namespace bits + { + int32_t NumberOfTrailingZerosI32(int32_t i) + { + int32_t y; + + if (i == 0) return 32; + + int32_t n = 31; + + y = i << 16; + + if (y != 0) { + n = n - 16; + i = y; + } + + y = i << 8; + + if (y != 0) { + n = n - 8; + i = y; + } + + y = i << 4; + + if (y != 0) { + n = n - 4; + i = y; + } + + y = i << 2; + + if (y != 0) { + n = n - 2; + i = y; + } + + return n - static_cast(static_cast(i << 1) >> 31); + } + + int32_t NumberOfLeadingZerosI32(int32_t i) + { + return NumberOfLeadingZerosU32(static_cast(i)); + } + + int32_t NumberOfLeadingZerosU32(uint32_t i) + { + if (i == 0) + return 32; + + int32_t n = 1; + + if (i >> 16 == 0) { + n += 16; + i <<= 16; + } + + if (i >> 24 == 0) { + n += 8; + i <<= 8; + } + + if (i >> 28 == 0) { + n += 4; + i <<= 4; + } + + if (i >> 30 == 0) { + n += 2; + i <<= 2; + } + + return n - static_cast(i >> 31); + } + + int32_t NumberOfLeadingZerosI64(int64_t i) + { + return NumberOfLeadingZerosU64(static_cast(i)); + } + + int32_t NumberOfLeadingZerosU64(uint64_t i) + { + if (i == 0) + return 64; + + int32_t n = 1; + + uint32_t x = static_cast(i >> 32); + + if (x == 0) { + n += 32; + x = static_cast(i); + } + + if (x >> 16 == 0) { + n += 16; + x <<= 16; + } + + if (x >> 24 == 0) { + n += 8; + x <<= 8; + } + + if (x >> 28 == 0) { + n += 4; + x <<= 4; + } + + if (x >> 30 == 0) { + n += 2; + x <<= 2; + } + + n -= x >> 31; + + return n; + } + + int32_t BitCountI32(int32_t i) + { + uint32_t ui = static_cast(i); + + ui -= (ui >> 1) & 0x55555555; + ui = (ui & 0x33333333) + ((ui >> 2) & 0x33333333); + ui = (ui + (ui >> 4)) & 0x0f0f0f0f; + ui += ui >> 8; + ui += ui >> 16; + + return static_cast(ui & 0x3f); + } + + int32_t BitLengthI32(int32_t i) + { + return 32 - NumberOfLeadingZerosI32(i); + } + + int32_t BitLengthU32(uint32_t i) + { + return 32 - NumberOfLeadingZerosU32(i); + } + + int32_t GetCapasityForSize(int32_t size) + { + assert(size > 0); + + if (size <= 8) + return 8; + + int32_t bl = BitLengthI32(size); + + if (bl > 30) + return INT32_MAX; + + int32_t res = 1 << bl; + + return size > res ? res << 1 : res; + } + + int32_t DigitLength(uint64_t x) + { + // See http://graphics.stanford.edu/~seander/bithacks.html + // for the details on the algorithm. + + if (x < 10) + return 1; + + int32_t r = ((64 - NumberOfLeadingZerosU64(x) + 1) * 1233) >> 12; + + assert(r <= UINT64_MAX_PRECISION); + + return (r == UINT64_MAX_PRECISION || x < TenPowerU64(r)) ? r : r + 1; + } + + uint64_t TenPowerU64(int32_t n) + { + static const uint64_t TEN_POWERS_TABLE[UINT64_MAX_PRECISION] = { + 1U, // 0 / 10^0 + 10U, // 1 / 10^1 + 100U, // 2 / 10^2 + 1000U, // 3 / 10^3 + 10000U, // 4 / 10^4 + 100000U, // 5 / 10^5 + 1000000U, // 6 / 10^6 + 10000000U, // 7 / 10^7 + 100000000U, // 8 / 10^8 + 1000000000U, // 9 / 10^9 + 10000000000U, // 10 / 10^10 + 100000000000U, // 11 / 10^11 + 1000000000000U, // 12 / 10^12 + 10000000000000U, // 13 / 10^13 + 100000000000000U, // 14 / 10^14 + 1000000000000000U, // 15 / 10^15 + 10000000000000000U, // 16 / 10^16 + 100000000000000000U, // 17 / 10^17 + 1000000000000000000U, // 18 / 10^18 + 10000000000000000000U // 19 / 10^19 + }; + + assert(n >= 0 && n < UINT64_MAX_PRECISION); + + return TEN_POWERS_TABLE[n]; + } + } + } + } +} diff --git a/src/odbc/src/common/concurrent.cpp b/src/odbc/src/common/concurrent.cpp new file mode 100644 index 000000000..1d041644c --- /dev/null +++ b/src/odbc/src/common/concurrent.cpp @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ignite/odbc/common/concurrent.h" + +namespace ignite +{ + namespace odbc + { + namespace common + { + namespace concurrent + { + /** Thread-local index generator for application. */ + int32_t appTlsIdxGen = 0; + + int32_t ThreadLocal::NextIndex() + { + return Atomics::IncrementAndGet32(&appTlsIdxGen); + } + + void ThreadLocal::Remove(int32_t idx) + { + void* val = Get0(); + + if (val) + { + std::map* map = + static_cast*>(val); + + ThreadLocalEntry* appVal = (*map)[idx]; + + if (appVal) + delete appVal; + + map->erase(idx); + + if (map->size() == 0) + { + delete map; + + Set0(NULL); + } + } + } + + void ThreadLocal::Clear0(void* mapPtr) + { + if (mapPtr) + { + std::map* map = + static_cast*>(mapPtr); + + for (std::map::iterator it = map->begin(); it != map->end(); ++it) + delete it->second; + + delete map; + } + } + + SharedPointerImpl::SharedPointerImpl(void* ptr, DeleterType deleter) : + ptr(ptr), deleter(deleter), refCnt(1) + { + Memory::Fence(); + } + + void* SharedPointerImpl::Pointer() + { + return ptr; + } + + const void* SharedPointerImpl::Pointer() const + { + return ptr; + } + + SharedPointerImpl::DeleterType SharedPointerImpl::Deleter() + { + return deleter; + } + + void SharedPointerImpl::Increment() + { + Atomics::IncrementAndGet32(&refCnt); + } + + bool SharedPointerImpl::Decrement() + { + return Atomics::DecrementAndGet32(&refCnt) == 0; + } + } + } + } +} diff --git a/src/odbc/src/common/decimal.cpp b/src/odbc/src/common/decimal.cpp new file mode 100644 index 000000000..40d597547 --- /dev/null +++ b/src/odbc/src/common/decimal.cpp @@ -0,0 +1,278 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "ignite/odbc/common/utils.h" +#include "ignite/odbc/common/decimal.h" + +using ignite::odbc::common::BigInteger; + +namespace ignite +{ + namespace odbc + { + namespace common + { + Decimal::Decimal() : + scale(0), + magnitude(0) + { + // No-op. + } + + Decimal::Decimal(const int8_t* mag, int32_t len, int32_t scale, int32_t sign, bool bigEndian) : + scale(scale & 0x7FFFFFFF), + magnitude(mag, len, sign, bigEndian) + { + // No-op. + } + + Decimal::Decimal(const Decimal& other) : + scale(other.scale), + magnitude(other.magnitude) + { + // No-op. + } + + Decimal::Decimal(int64_t val) : + scale(0), + magnitude(val) + { + // No-op. + } + + Decimal::Decimal(int64_t val, int32_t scale) : + scale(scale), + magnitude(val) + { + // No-op. + } + + Decimal::Decimal(const BigInteger& val, int32_t scale) : + scale(scale), + magnitude(val) + { + // No-op. + } + + Decimal::Decimal(const char* val, int32_t len) : + scale(0), + magnitude(0) + { + AssignString(val, len); + } + + Decimal::~Decimal() + { + // No-op. + } + + Decimal& Decimal::operator=(const Decimal& other) + { + scale = other.scale; + magnitude = other.magnitude; + + return *this; + } + + Decimal::operator double() const + { + return ToDouble(); + } + + Decimal::operator int64_t() const + { + return ToInt64(); + } + + double Decimal::ToDouble() const + { + return common::LexicalCast(*this); + } + + int64_t Decimal::ToInt64() const + { + if (scale == 0) + return magnitude.ToInt64(); + + Decimal zeroScaled; + + SetScale(0, zeroScaled); + + return zeroScaled.magnitude.ToInt64(); + } + + int32_t Decimal::GetScale() const + { + return scale; + } + + void Decimal::SetScale(int32_t newScale, Decimal& res) const + { + if (scale == newScale) + return; + + int32_t diff = scale - newScale; + + BigInteger adjustment; + + if (diff > 0) + { + BigInteger::GetPowerOfTen(diff, adjustment); + + magnitude.Divide(adjustment, res.magnitude); + } + else + { + BigInteger::GetPowerOfTen(-diff, adjustment); + + magnitude.Multiply(adjustment, res.magnitude); + } + + res.scale = newScale; + } + + int32_t Decimal::GetPrecision() const + { + return magnitude.GetPrecision(); + } + + const BigInteger& Decimal::GetUnscaledValue() const + { + return magnitude; + } + + void Decimal::Swap(Decimal& second) + { + using std::swap; + + swap(scale, second.scale); + magnitude.Swap(second.magnitude); + } + + int32_t Decimal::GetMagnitudeLength() const + { + return magnitude.mag.GetSize(); + } + + void Decimal::AssignString(const char* val, int32_t len) + { + std::stringstream converter; + + converter.write(val, len); + + converter >> *this; + } + + void Decimal::AssignInt64(int64_t val) + { + magnitude.AssignInt64(val); + + scale = 0; + } + + void Decimal::AssignDouble(double val) + { + std::stringstream converter; + + converter.precision(16); + + converter << val; + converter >> *this; + } + + void Decimal::AssignUint64(uint64_t val) + { + magnitude.AssignUint64(val); + + scale = 0; + } + + int32_t Decimal::Compare(const Decimal& other) const + { + if (IsZero() && other.IsZero()) + return 0; + + if (scale == other.scale) + return magnitude.Compare(other.magnitude); + else if (scale > other.scale) + { + Decimal scaled; + + other.SetScale(scale, scaled); + + return magnitude.Compare(scaled.magnitude); + } + else + { + Decimal scaled; + + SetScale(other.scale, scaled); + + return scaled.magnitude.Compare(other.magnitude); + } + } + + bool Decimal::IsNegative() const + { + return magnitude.IsNegative(); + } + + bool Decimal::IsZero() const + { + return magnitude.IsZero(); + } + + bool Decimal::IsPositive() const + { + return magnitude.IsPositive(); + } + + bool operator==(const Decimal& val1, const Decimal& val2) + { + return val1.Compare(val2) == 0; + } + + bool operator!=(const Decimal& val1, const Decimal& val2) + { + return val1.Compare(val2) != 0; + } + + bool operator<(const Decimal& val1, const Decimal& val2) + { + return val1.Compare(val2) < 0; + } + + bool operator<=(const Decimal& val1, const Decimal& val2) + { + return val1.Compare(val2) <= 0; + } + + bool operator>(const Decimal& val1, const Decimal& val2) + { + return val1.Compare(val2) > 0; + } + + bool operator>=(const Decimal& val1, const Decimal& val2) + { + return val1.Compare(val2) >= 0; + } + } + } +} diff --git a/src/odbc/src/common/utils.cpp b/src/odbc/src/common/utils.cpp new file mode 100644 index 000000000..5dc44111f --- /dev/null +++ b/src/odbc/src/common/utils.cpp @@ -0,0 +1,219 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +namespace ignite +{ + namespace odbc + { + namespace common + { + /** + * Check if string ends with the given ending. + * + * @param str String to check. + * @param ending Ending. + * @return Result. + */ + inline bool StringEndsWith(const std::string& str, const std::string& ending) + { + if (str.length() > ending.length()) + return str.compare(str.length() - ending.length(), ending.length(), ending) == 0; + + return false; + } + + void StripSurroundingWhitespaces(std::string& str) + { + std::string::size_type newBegin = 0; + while (newBegin < str.size() && ::isspace(str[newBegin])) + ++newBegin; + + if (newBegin == str.size()) + { + str.clear(); + + return; + } + + std::string::size_type newEnd = str.size() - 1; + while (::isspace(str[newEnd])) + --newEnd; + + str.assign(str, newBegin, (newEnd - newBegin) + 1); + } + + char* CopyChars(const char* val) + { + if (val) { + size_t len = strlen(val); + char* dest = new char[len + 1]; + strcpy(dest, val); + *(dest + len) = 0; + return dest; + } + + return 0; + } + + void ReleaseChars(char* val) + { + // Its OK to delete null-pointer. + delete[] val; + } + + uint32_t ToBigEndian(uint32_t value) + { + // The answer is 42 + static const int num = 42; + static const bool isLittleEndian = (*reinterpret_cast(&num) == num); + + if (isLittleEndian) + return ((value & 0xFF) << 24) | (((value >> 8) & 0xFF) << 16) | (((value >> 16) & 0xFF) << 8) | ((value >> 24) & 0xFF); + + return value; + } + + IGNITE_FRIEND_EXPORT Date MakeDateGmt(int year, int month, int day, int hour, + int min, int sec) + { + tm date; + + std::memset(&date, 0, sizeof(date)); + + date.tm_year = year - 1900; + date.tm_mon = month - 1; + date.tm_mday = day; + date.tm_hour = hour; + date.tm_min = min; + date.tm_sec = sec; + + return CTmToDate(date); + } + + IGNITE_FRIEND_EXPORT Date MakeDateLocal(int year, int month, int day, int hour, + int min, int sec) + { + tm date; + + std::memset(&date, 0, sizeof(date)); + + date.tm_year = year - 1900; + date.tm_mon = month - 1; + date.tm_mday = day; + date.tm_hour = hour; + date.tm_min = min; + date.tm_sec = sec; + + time_t localTime = common::IgniteTimeLocal(date); + + return CTimeToDate(localTime); + } + + IGNITE_FRIEND_EXPORT Time MakeTimeGmt(int hour, int min, int sec) + { + tm date; + + std::memset(&date, 0, sizeof(date)); + + date.tm_year = 70; + date.tm_mon = 0; + date.tm_mday = 1; + date.tm_hour = hour; + date.tm_min = min; + date.tm_sec = sec; + + return CTmToTime(date); + } + + IGNITE_FRIEND_EXPORT Time MakeTimeLocal(int hour, int min, int sec) + { + tm date; + + std::memset(&date, 0, sizeof(date)); + + date.tm_year = 70; + date.tm_mon = 0; + date.tm_mday = 1; + date.tm_hour = hour; + date.tm_min = min; + date.tm_sec = sec; + + time_t localTime = common::IgniteTimeLocal(date); + + return CTimeToTime(localTime); + } + + IGNITE_FRIEND_EXPORT Timestamp MakeTimestampGmt(int year, int month, int day, + int hour, int min, int sec, long ns) + { + tm date; + + std::memset(&date, 0, sizeof(date)); + + date.tm_year = year - 1900; + date.tm_mon = month - 1; + date.tm_mday = day; + date.tm_hour = hour; + date.tm_min = min; + date.tm_sec = sec; + + return CTmToTimestamp(date, ns); + } + + IGNITE_FRIEND_EXPORT Timestamp MakeTimestampLocal(int year, int month, int day, + int hour, int min, int sec, long ns) + { + tm date; + + std::memset(&date, 0, sizeof(date)); + + date.tm_year = year - 1900; + date.tm_mon = month - 1; + date.tm_mday = day; + date.tm_hour = hour; + date.tm_min = min; + date.tm_sec = sec; + + time_t localTime = common::IgniteTimeLocal(date); + + return CTimeToTimestamp(localTime, ns); + } + + IGNITE_IMPORT_EXPORT std::string GetDynamicLibraryName(const char* name) + { + std::stringstream libNameBuffer; + + libNameBuffer << name << Dle; + + return libNameBuffer.str(); + } + + IGNITE_IMPORT_EXPORT bool AllDigits(const std::string &val) + { + std::string::const_iterator i = val.begin(); + + while (i != val.end() && isdigit(*i)) + ++i; + + return i == val.end(); + } + + } + } +} diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index 066ffab76..4bdc511f7 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -21,8 +21,7 @@ #include #include -#include - +#include #include #include "ignite/odbc/log.h" @@ -37,6 +36,10 @@ #include "ignite/odbc/config/configuration.h" #include "ignite/odbc/config/connection_string_parser.h" #include "ignite/odbc/system/system_dsn.h" +#include "ignite/odbc/jni/java.h" +#include "ignite/odbc/jni/utils.h" +#include "ignite/odbc/common/concurrent.h" +#include "ignite/odbc/common/utils.h" // Uncomment for per-byte debug. //#define PER_BYTE_DEBUG @@ -58,16 +61,16 @@ namespace ignite { Connection::Connection(Environment* env) : env(env), - socket(), timeout(0), loginTimeout(DEFAULT_CONNECT_TIMEOUT), autoCommit(true), parser(), config(), info(config), - streamingContext() + connection(), + opts() { - streamingContext.SetConnection(*this); + // No-op } Connection::~Connection() @@ -144,47 +147,15 @@ namespace ignite IGNITE_ODBC_API_CALL(InternalEstablish(cfg)); } - SqlResult::Type Connection::InitSocket() - { - // Removed SSL Mode in DSN. Replaced this with REQUIRE for now. - ssl::SslMode::Type sslMode = ssl::SslMode::REQUIRE; - - if (sslMode == ssl::SslMode::DISABLE) - { - socket.reset(network::ssl::MakeTcpSocketClient()); - - return SqlResult::AI_SUCCESS; - } - - try - { - network::ssl::EnsureSslLoaded(); - } - catch (const IgniteError &err) - { - LOG_MSG("Can not load OpenSSL library: " << err.GetText()); - - AddStatusRecord("Can not load OpenSSL library (did you set OPENSSL_HOME environment variable?)"); - - return SqlResult::AI_ERROR; - } - - // Removed SSL key and cert files from DSN. Replaced with empty string for now. - socket.reset(network::ssl::MakeSecureSocketClient( - "", "", config.GetTlsCaFile())); - - return SqlResult::AI_SUCCESS; - } - SqlResult::Type Connection::InternalEstablish(const config::Configuration& cfg) { using ssl::SslMode; config = cfg; - if (socket.get() != 0) - { - AddStatusRecord(SqlState::S08002_ALREADY_CONNECTED, "Already connected."); + if (connection) { + AddStatusRecord(SqlState::S08002_ALREADY_CONNECTED, + "Already connected."); return SqlResult::AI_ERROR; } @@ -196,11 +167,15 @@ namespace ignite return SqlResult::AI_ERROR; } - bool connected = TryRestoreConnection(); + odbc::IgniteError err; + bool connected = TryRestoreConnection(err); if (!connected) { - AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, "Failed to establish connection with the host."); + std::string errMessage = "Failed to establish connection with the host.\n"; + errMessage.append(err.GetText()); + AddStatusRecord( + SqlState::S08001_CANNOT_CONNECT, errMessage); return SqlResult::AI_ERROR; } @@ -222,7 +197,7 @@ namespace ignite SqlResult::Type Connection::InternalRelease() { - if (socket.get() == 0) + if (!connection) { AddStatusRecord(SqlState::S08003_NOT_CONNECTED, "Connection is not open."); @@ -238,12 +213,19 @@ namespace ignite void Connection::Close() { - if (socket.get() != 0) - { - socket->Close(); - - socket.reset(); + if (connection) { + using namespace jni::java; + using namespace common::concurrent; + SharedPointer< JniContext > ctx(JniContext::Create(&opts[0], static_cast(opts.size()), JniHandlers())); + JniErrorInfo errInfo; + // NOTE: DocumentDbDisconnect will notify JNI connection is no longer used - must set to nullptr. + ctx.Get()->DocumentDbDisconnect(connection, &errInfo); + if (errInfo.code != java::IGNITE_JNI_ERR_SUCCESS) { + // TODO: Determine if we need to error check the close. + } + connection = nullptr; } + Deinit(); } Statement* Connection::CreateStatement() @@ -271,125 +253,26 @@ namespace ignite bool Connection::Send(const int8_t* data, size_t len, int32_t timeout) { - if (socket.get() == 0) - throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established"); - - int32_t newLen = static_cast(len + sizeof(OdbcProtocolHeader)); - - common::FixedSizeArray msg(newLen); - - OdbcProtocolHeader *hdr = reinterpret_cast(msg.GetData()); - - hdr->len = static_cast(len); - - memcpy(msg.GetData() + sizeof(OdbcProtocolHeader), data, len); - - OperationResult::T res = SendAll(msg.GetData(), msg.GetSize(), timeout); - - if (res == OperationResult::TIMEOUT) - return false; - - if (res == OperationResult::FAIL) - throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not send message due to connection failure"); - -#ifdef PER_BYTE_DEBUG - LOG_MSG("message sent: (" << msg.GetSize() << " bytes)" << utility::HexDump(msg.GetData(), msg.GetSize())); -#endif //PER_BYTE_DEBUG - + // TODO: Remove if unnecessary return true; } Connection::OperationResult::T Connection::SendAll(const int8_t* data, size_t len, int32_t timeout) { - int sent = 0; - - while (sent != static_cast(len)) - { - int res = socket->Send(data + sent, len - sent, timeout); - - LOG_MSG("Sent: " << res); - - if (res < 0 || res == network::SocketClient::WaitResult::TIMEOUT) - { - Close(); - - return res < 0 ? OperationResult::FAIL : OperationResult::TIMEOUT; - } - - sent += res; - } - - assert(static_cast(sent) == len); - + // TODO: Remove if unnecessary. + // No-op return OperationResult::SUCCESS; } bool Connection::Receive(std::vector& msg, int32_t timeout) { - if (socket.get() == 0) - throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established"); - - msg.clear(); - - OdbcProtocolHeader hdr; - - OperationResult::T res = ReceiveAll(reinterpret_cast(&hdr), sizeof(hdr), timeout); - - if (res == OperationResult::TIMEOUT) - return false; - - if (res == OperationResult::FAIL) - throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not receive message header"); - - if (hdr.len < 0) - { - Close(); - - throw OdbcError(SqlState::SHY000_GENERAL_ERROR, "Protocol error: Message length is negative"); - } - - if (hdr.len == 0) - return false; - - msg.resize(hdr.len); - - res = ReceiveAll(&msg[0], hdr.len, timeout); - - if (res == OperationResult::TIMEOUT) - return false; - - if (res == OperationResult::FAIL) - throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not receive message body"); - -#ifdef PER_BYTE_DEBUG - LOG_MSG("Message received: " << utility::HexDump(&msg[0], msg.size())); -#endif //PER_BYTE_DEBUG - + // TODO: Remove if unnecessary. return true; } Connection::OperationResult::T Connection::ReceiveAll(void* dst, size_t len, int32_t timeout) { - size_t remain = len; - int8_t* buffer = reinterpret_cast(dst); - - while (remain) - { - size_t received = len - remain; - - int res = socket->Receive(buffer + received, remain, timeout); - LOG_MSG("Receive res: " << res << " remain: " << remain); - - if (res < 0 || res == network::SocketClient::WaitResult::TIMEOUT) - { - Close(); - - return res < 0 ? OperationResult::FAIL : OperationResult::TIMEOUT; - } - - remain -= static_cast(res); - } - + // TODO: Remove if unnecessary. return OperationResult::SUCCESS; } @@ -445,7 +328,7 @@ namespace ignite return SqlResult::AI_ERROR; } - catch (const IgniteError& err) + catch (const odbc::IgniteError& err) { AddStatusRecord(err.GetText()); @@ -486,7 +369,7 @@ namespace ignite return SqlResult::AI_ERROR; } - catch (const IgniteError& err) + catch (const odbc::IgniteError& err) { AddStatusRecord(err.GetText()); @@ -516,7 +399,7 @@ namespace ignite { SQLUINTEGER *val = reinterpret_cast(buf); - *val = socket.get() != 0 ? SQL_CD_FALSE : SQL_CD_TRUE; + *val = connection ? SQL_CD_FALSE : SQL_CD_TRUE; if (valueLen) *valueLen = SQL_IS_INTEGER; @@ -681,7 +564,7 @@ namespace ignite return SqlResult::AI_ERROR; } - catch (const IgniteError& err) + catch (const odbc::IgniteError& err) { AddStatusRecord(SqlState::S08004_CONNECTION_REJECTED, err.GetText()); @@ -716,67 +599,177 @@ namespace ignite void Connection::EnsureConnected() { - if (socket.get() != 0) + if (connection) return; - bool success = TryRestoreConnection(); + odbc::IgniteError err; + bool success = TryRestoreConnection(err); if (!success) throw OdbcError(SqlState::S08001_CANNOT_CONNECT, "Failed to establish connection with any provided hosts"); } - bool Connection::TryRestoreConnection() + bool Connection::TryRestoreConnection(odbc::IgniteError& err) { - std::vector addrs; - - CollectAddresses(config, addrs); + bool connected = false; - if (socket.get() == 0) - { - SqlResult::Type res = InitSocket(); + using namespace jni::java; + using namespace common::concurrent; - if (res != SqlResult::AI_SUCCESS) - return false; + if (connection) { + return true; } - bool connected = false; + std::string connectionString = FormatJdbcConnectionString(); + JniErrorInfo errInfo; - while (!addrs.empty() && !connected) - { - const EndPoint& addr = addrs.back(); + std::string docdb_home = common::GetEnv("DOCUMENTDB_HOME") + + "\\documentdb-jdbc-1.1.0-all.jar"; + + // 2. Resolve DOCUMENTDB_HOME. + std::string home = jni::ResolveDocumentDbHome(); - for (uint16_t port = addr.port; port <= addr.port + addr.range; ++port) - { - try - { - connected = socket->Connect(addr.host.c_str(), port, loginTimeout); - } - catch (const IgniteError& err) - { - LOG_MSG("Error while trying connect to " << addr.host << ":" << addr.port <<", " << err.GetText()); - } + // 3. Create classpath. + std::string cp = jni::CreateDocumentDbClasspath(std::string(), home); - if (connected) - { - SqlResult::Type res = MakeRequestHandshake(); + if (cp.empty()) { + err = + odbc::IgniteError(odbc::IgniteError::IGNITE_ERR_JVM_NO_CLASSPATH, + "Java classpath is empty (did you set " + "DOCUMENTDB_HOME environment variable?)"); - connected = res != SqlResult::AI_ERROR; + return false; + } - if (connected) - break; - } + SetJvmOptions(cp); + + SharedPointer< JniContext > ctx(JniContext::Create(&opts[0], static_cast(opts.size()), JniHandlers(), &errInfo)); + if (ctx.Get()) { + jobject result = ctx.Get()->DocumentDbConnect( + connectionString.c_str(), &errInfo); + connected = (result && errInfo.code == java::IGNITE_JNI_ERR_SUCCESS); + if (!connected) { + err = odbc::IgniteError( + odbc::IgniteError::IGNITE_ERR_SECURE_CONNECTION_FAILURE, + errInfo.errMsg); + Close(); } - - addrs.pop_back(); + connection = result; + } else { + err = odbc::IgniteError(odbc::IgniteError::IGNITE_ERR_JVM_INIT, "Unable to get initialized JVM."); + connection = nullptr; } - if (!connected) - Close(); - return connected; } + std::string Connection::FormatJdbcConnectionString() const { + std::string host = "localhost"; + std::string port = "27017"; + if (!config.GetAddresses().empty()) { + host = config.GetAddresses()[0].host; + port = std::to_string(config.GetAddresses()[0].port); + } + std::string jdbConnectionString; + + jdbConnectionString = "jdbc:documentdb:"; + jdbConnectionString.append("//" + config.GetUser()); + jdbConnectionString.append(":" + config.GetPassword()); + jdbConnectionString.append("@" + host); + jdbConnectionString.append(":" + port); + jdbConnectionString.append("/" + config.GetSchema()); + jdbConnectionString.append("?tlsAllowInvalidHostnames=true"); + + // Check if internal SSH tunnel should be enabled. + // TODO: Remove use of environment variables and use DSN properties + std::string sshUserAtHost = common::GetEnv("DOC_DB_USER", ""); + std::string sshRemoteHost = common::GetEnv("DOC_DB_HOST", ""); + std::string sshPrivKeyFile = common::GetEnv("DOC_DB_PRIV_KEY_FILE", ""); + std::string sshUser; + std::string sshTunnelHost; + size_t indexOfAt = sshUserAtHost.find_first_of('@'); + if (indexOfAt >= 0 && sshUserAtHost.size() > (indexOfAt + 1)) { + sshUser = sshUserAtHost.substr(0, indexOfAt); + sshTunnelHost = sshUserAtHost.substr(indexOfAt + 1); + } + if (!sshUserAtHost.empty() + && !sshRemoteHost.empty() + && !sshPrivKeyFile.empty() + && !sshUser.empty() + && !sshTunnelHost.empty()) { + jdbConnectionString.append("&sshUser=" + sshUser); + jdbConnectionString.append("&sshHost=" + sshTunnelHost); + jdbConnectionString.append("&sshPrivateKeyFile=" + sshPrivKeyFile); + jdbConnectionString.append("&sshStrictHostKeyChecking=false"); + } + + return jdbConnectionString; + } + + /** + * Create JVM options from configuration. + * + * @param cfg Configuration. + * @param home Optional GG home. + * @param cp Classpath. + */ + void Connection::SetJvmOptions(const std::string& cp) { + using namespace common; + Deinit(); + + const size_t REQ_OPTS_CNT = 4; + const size_t JAVA9_OPTS_CNT = 6; + + opts.reserve(REQ_OPTS_CNT + JAVA9_OPTS_CNT); + + // 1. Set classpath. + std::string cpFull = "-Djava.class.path=" + cp; + + opts.push_back(CopyChars(cpFull.c_str())); + + // 3. Set Xms, Xmx. + std::string xmsStr = "-Xms" + std::to_string(256) + "m"; + std::string xmxStr = "-Xmx" + std::to_string(1024) + "m"; + + opts.push_back(CopyChars(xmsStr.c_str())); + opts.push_back(CopyChars(xmxStr.c_str())); + + // 4. Optional debug arguments + //std::string debugStr = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"; + //opts.push_back(CopyChars(debugStr.c_str())); + + // 5. Set file.encoding. + std::string fileEncParam = "-Dfile.encoding="; + std::string fileEncFull = fileEncParam + "UTF-8"; + opts.push_back(CopyChars(fileEncFull.c_str())); + + // Adding options for Java 9 or later + if (jni::java::IsJava9OrLater()) { + opts.push_back(CopyChars( + "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED")); + opts.push_back(CopyChars( + "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED")); + opts.push_back(CopyChars( + "--add-exports=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED")); + opts.push_back(CopyChars( + "--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED")); + opts.push_back(CopyChars( + "--add-exports=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED")); + opts.push_back(CopyChars( + "--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED")); + } + } + + /** + * Deallocates all allocated data. + */ + void Connection::Deinit() { + using namespace common; + std::for_each(opts.begin(), opts.end(), ReleaseChars); + opts.clear(); + } + void Connection::CollectAddresses(const config::Configuration& cfg, std::vector& endPoints) { endPoints.clear(); @@ -806,14 +799,6 @@ namespace ignite { SQLUINTEGER uTimeout = static_cast(reinterpret_cast(value)); - if (uTimeout != 0 && socket.get() != 0 && socket->IsBlocking()) - { - AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, "Can not set timeout, because can not " - "enable non-blocking mode on TCP connection. Setting to 0."); - - return 0; - } - if (uTimeout > INT32_MAX) { std::stringstream ss; diff --git a/src/odbc/src/ignite_error.cpp b/src/odbc/src/ignite_error.cpp new file mode 100644 index 000000000..23841d413 --- /dev/null +++ b/src/odbc/src/ignite_error.cpp @@ -0,0 +1,227 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include +#include + +using namespace ignite::odbc::common; +using namespace ignite::odbc::java; + +namespace ignite +{ + namespace odbc + { + void IgniteError::ThrowIfNeeded(const IgniteError& err) + { + if (err.code != IGNITE_SUCCESS) + throw err; + } + + IgniteError::IgniteError() : + code(IGNITE_SUCCESS), + msg(NULL) + { + // No-op. + } + + IgniteError::IgniteError(int32_t code) : + code(code), + msg(NULL) + { + } + + IgniteError::IgniteError(int32_t code, const char* msg) : + code(code), + msg(CopyChars(msg)) + { + // No-op. + } + + IgniteError::IgniteError(const IgniteError& other) : + code(other.code), + msg(CopyChars(other.msg)) + { + // No-op. + } + + IgniteError& IgniteError::operator=(const IgniteError& other) + { + if (this != &other) + { + IgniteError tmp(other); + + std::swap(code, tmp.code); + std::swap(msg, tmp.msg); + } + + return *this; + } + + IgniteError::~IgniteError() IGNITE_NO_THROW + { + ReleaseChars(msg); + } + + int32_t IgniteError::GetCode() const + { + return code; + } + + const char* IgniteError::GetText() const IGNITE_NO_THROW + { + if (code == IGNITE_SUCCESS) + return "Operation completed successfully."; + else if (msg) + return msg; + else + return "No additional information available."; + } + + const char* IgniteError::what() const IGNITE_NO_THROW + { + return GetText(); + } + + void IgniteError::SetError(const int jniCode, const char* jniCls, const char* jniMsg, IgniteError& err) + { + if (jniCode == IGNITE_JNI_ERR_SUCCESS) + err = IgniteError(); + else if (jniCode == IGNITE_JNI_ERR_GENERIC) + { + // The most common case when we have Java exception "in hands" and must map it to respective code. + if (jniCls) + { + std::string jniCls0 = jniCls; + + if (jniCls0.compare("java.lang.NoClassDefFoundError") == 0) + { + std::stringstream stream; + + stream << "Java class is not found (did you set DOCUMENTDB_HOME environment variable?)"; + + if (jniMsg) + stream << ": " << jniMsg; + + err = IgniteError(IGNITE_ERR_JVM_NO_CLASS_DEF_FOUND, stream.str().c_str()); + } + else if (jniCls0.compare("java.lang.NoSuchMethodError") == 0) + { + std::stringstream stream; + + stream << "Java method is not found (did you set DOCUMENTDB_HOME environment variable?)"; + + if (jniMsg) + stream << ": " << jniMsg; + + err = IgniteError(IGNITE_ERR_JVM_NO_SUCH_METHOD, stream.str().c_str()); + } + else if (jniCls0.compare("java.lang.IllegalArgumentException") == 0) + err = IgniteError(IGNITE_ERR_ILLEGAL_ARGUMENT, jniMsg); + else if (jniCls0.compare("java.lang.IllegalStateException") == 0) + err = IgniteError(IGNITE_ERR_ILLEGAL_STATE, jniMsg); + else if (jniCls0.compare("java.lang.UnsupportedOperationException") == 0) + err = IgniteError(IGNITE_ERR_UNSUPPORTED_OPERATION, jniMsg); + else if (jniCls0.compare("java.lang.InterruptedException") == 0) + err = IgniteError(IGNITE_ERR_INTERRUPTED, jniMsg); + else if (jniCls0.compare("org.apache.ignite.cluster.ClusterGroupEmptyException") == 0) + err = IgniteError(IGNITE_ERR_CLUSTER_GROUP_EMPTY, jniMsg); + else if (jniCls0.compare("org.apache.ignite.cluster.ClusterTopologyException") == 0) + err = IgniteError(IGNITE_ERR_CLUSTER_TOPOLOGY, jniMsg); + else if (jniCls0.compare("org.apache.ignite.compute.ComputeExecutionRejectedException") == 0) + err = IgniteError(IGNITE_ERR_COMPUTE_EXECUTION_REJECTED, jniMsg); + else if (jniCls0.compare("org.apache.ignite.compute.ComputeJobFailoverException") == 0) + err = IgniteError(IGNITE_ERR_COMPUTE_JOB_FAILOVER, jniMsg); + else if (jniCls0.compare("org.apache.ignite.compute.ComputeTaskCancelledException") == 0) + err = IgniteError(IGNITE_ERR_COMPUTE_TASK_CANCELLED, jniMsg); + else if (jniCls0.compare("org.apache.ignite.compute.ComputeTaskTimeoutException") == 0) + err = IgniteError(IGNITE_ERR_COMPUTE_TASK_TIMEOUT, jniMsg); + else if (jniCls0.compare("org.apache.ignite.compute.ComputeUserUndeclaredException") == 0) + err = IgniteError(IGNITE_ERR_COMPUTE_USER_UNDECLARED_EXCEPTION, jniMsg); + else if (jniCls0.compare("javax.cache.CacheException") == 0) + err = IgniteError(IGNITE_ERR_CACHE, jniMsg); + else if (jniCls0.compare("javax.cache.integration.CacheLoaderException") == 0) + err = IgniteError(IGNITE_ERR_CACHE_LOADER, jniMsg); + else if (jniCls0.compare("javax.cache.integration.CacheWriterException") == 0) + err = IgniteError(IGNITE_ERR_CACHE_WRITER, jniMsg); + else if (jniCls0.compare("javax.cache.processor.EntryProcessorException") == 0) + err = IgniteError(IGNITE_ERR_ENTRY_PROCESSOR, jniMsg); + else if (jniCls0.compare("org.apache.ignite.cache.CachePartialUpdateException") == 0) + err = IgniteError(IGNITE_ERR_CACHE_PARTIAL_UPDATE, jniMsg); + else if (jniCls0.compare("org.apache.ignite.transactions.TransactionOptimisticException") == 0) + err = IgniteError(IGNITE_ERR_TX_OPTIMISTIC, jniMsg); + else if (jniCls0.compare("org.apache.ignite.transactions.TransactionTimeoutException") == 0) + err = IgniteError(IGNITE_ERR_TX_TIMEOUT, jniMsg); + else if (jniCls0.compare("org.apache.ignite.transactions.TransactionRollbackException") == 0) + err = IgniteError(IGNITE_ERR_TX_ROLLBACK, jniMsg); + else if (jniCls0.compare("org.apache.ignite.transactions.TransactionHeuristicException") == 0) + err = IgniteError(IGNITE_ERR_TX_HEURISTIC, jniMsg); + else if (jniCls0.compare("org.apache.ignite.IgniteAuthenticationException") == 0) + err = IgniteError(IGNITE_ERR_AUTHENTICATION, jniMsg); + else if (jniCls0.compare("org.apache.ignite.plugin.security.GridSecurityException") == 0) + err = IgniteError(IGNITE_ERR_SECURITY, jniMsg); + else if (jniCls0.compare("org.apache.ignite.IgniteException") == 0) + err = IgniteError(IGNITE_ERR_GENERIC, jniMsg); + else if (jniCls0.compare("org.apache.ignite.IgniteCheckedException") == 0) + err = IgniteError(IGNITE_ERR_GENERIC, jniMsg); + else + { + std::stringstream stream; + + stream << "Java exception occurred [cls=" << jniCls0; + + if (jniMsg) + stream << ", msg=" << jniMsg; + + stream << "]"; + + err = IgniteError(IGNITE_ERR_UNKNOWN, stream.str().c_str()); + } + } + else + { + // JNI class name is not available. Something really weird. + err = IgniteError(IGNITE_ERR_UNKNOWN); + } + } + else if (jniCode == IGNITE_JNI_ERR_JVM_INIT) + { + std::stringstream stream; + + stream << "Failed to initialize JVM [errCls="; + + if (jniCls) + stream << jniCls; + else + stream << "N/A"; + + stream << ", errMsg="; + + if (jniMsg) + stream << jniMsg; + else + stream << "N/A"; + + stream << "]"; + + err = IgniteError(IGNITE_ERR_JVM_INIT, stream.str().c_str()); + } + else if (jniCode == IGNITE_JNI_ERR_JVM_ATTACH) + err = IgniteError(IGNITE_ERR_JVM_ATTACH, "Failed to attach to JVM."); + } + } +} diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp new file mode 100644 index 000000000..dcd21b0b3 --- /dev/null +++ b/src/odbc/src/jni/java.cpp @@ -0,0 +1,1102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ReSharper disable once CppUnusedIncludeDirective +#include // needed only on linux +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifndef JNI_VERSION_9 +#define JNI_VERSION_9 0x00090000 +#endif // JNI_VERSION_9 + +#define IGNITE_SAFE_PROC_NO_ARG(jniEnv, envPtr, type, field) { \ + JniHandlers* hnds = reinterpret_cast(envPtr); \ + type hnd = hnds->field; \ + if (hnd) \ + { \ + try \ + { \ + hnd(hnds->target); \ + } \ + catch (std::exception& err) \ + { \ + ThrowToJava(jniEnv, err.what()); \ + } \ + } \ + else \ + ThrowOnMissingHandler(jniEnv); \ +} + +#define IGNITE_SAFE_PROC(jniEnv, envPtr, type, field, ...) { \ + JniHandlers* hnds = reinterpret_cast(envPtr); \ + type hnd = hnds->field; \ + if (hnd) \ + { \ + try \ + { \ + hnd(hnds->target, __VA_ARGS__); \ + } \ + catch (std::exception& err) \ + { \ + ThrowToJava(jniEnv, err.what()); \ + } \ + } \ + else \ + ThrowOnMissingHandler(jniEnv); \ +} + +#define IGNITE_SAFE_FUNC(jniEnv, envPtr, type, field, ...) { \ + JniHandlers* hnds = reinterpret_cast(envPtr); \ + type hnd = hnds->field; \ + if (hnd) \ + { \ + try \ + { \ + return hnd(hnds->target, __VA_ARGS__); \ + } \ + catch (std::exception& err) \ + { \ + ThrowToJava(jniEnv, err.what()); \ + return 0; \ + } \ + } \ + else \ + { \ + ThrowOnMissingHandler(jniEnv); \ + return 0; \ + }\ +} + +using namespace ignite::odbc::java; + +namespace ignite +{ + namespace odbc + { + namespace jni + { + namespace java + { + namespace iocc = ignite::odbc::common::concurrent; + + bool IGNITE_IMPORT_EXPORT IsJava9OrLater() + { + JavaVMInitArgs args; + + memset(&args, 0, sizeof(args)); + + args.version = JNI_VERSION_9; + + return JNI_GetDefaultJavaVMInitArgs(&args) == JNI_OK; + } + + /* --- Startup exception. --- */ + class JvmException : public std::exception { + // No-op. + }; + + /* --- JNI method definitions. --- */ + struct JniMethod { + char* name; + char* sign; + bool isStatic; + + JniMethod(const char* name, const char* sign, bool isStatic) + : name(const_cast< char* >(name)), + sign(const_cast< char* >(sign)), + isStatic(isStatic) { + } + }; + + JniErrorInfo::JniErrorInfo() : code(IGNITE_JNI_ERR_SUCCESS) + { + // No-op. + } + + JniErrorInfo::JniErrorInfo(int code, const char* errCls, const char* errMsg) : code(code) + { + this->errCls = common::CopyChars(errCls); + this->errMsg = common::CopyChars(errMsg); + } + + JniErrorInfo::JniErrorInfo(const JniErrorInfo& other) : code(other.code) + { + this->errCls = common::CopyChars(other.errCls); + this->errMsg = common::CopyChars(other.errMsg); + } + + JniErrorInfo& JniErrorInfo::operator=(const JniErrorInfo& other) + { + if (this != &other) + { + // 1. Create new instance, exception could occur at this point. + JniErrorInfo tmp(other); + + // 2. Swap with temp. + std::swap(code, tmp.code); + std::swap(errCls, tmp.errCls); + std::swap(errMsg, tmp.errMsg); + } + + return *this; + } + + JniErrorInfo::~JniErrorInfo() + { + delete[] errCls; + delete[] errMsg; + } + + /** + * Guard to ensure global reference cleanup. + */ + class JniGlobalRefGuard + { + public: + JniGlobalRefGuard(JNIEnv *e, jobject obj) : env(e), ref(obj) + { + // No-op. + } + + ~JniGlobalRefGuard() + { + env->DeleteGlobalRef(ref); + } + + private: + /** Environment. */ + JNIEnv* env; + + /** Target reference. */ + jobject ref; + + IGNITE_NO_COPY_ASSIGNMENT(JniGlobalRefGuard); + }; + + const char* C_THROWABLE = "java/lang/Throwable"; + JniMethod M_THROWABLE_GET_MESSAGE = JniMethod("getMessage", "()Ljava/lang/String;", false); + JniMethod M_THROWABLE_PRINT_STACK_TRACE = JniMethod("printStackTrace", "()V", false); + + const char* C_CLASS = "java/lang/Class"; + JniMethod M_CLASS_GET_NAME = JniMethod("getName", "()Ljava/lang/String;", false); + + const char* C_DOCUMENTDB_CONNECTION_PROPERTIES = + "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; + JniMethod M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING = + JniMethod( + "getPropertiesFromConnectionString", + "(Ljava/lang/String;)Lsoftware/amazon/documentdb/jdbc/DocumentDbConnectionProperties;", + true); + + const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; + + const char* C_DRIVERMANAGER = "java/sql/DriverManager"; + JniMethod M_DRIVERMANAGER_GET_CONNECTION = + JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); + + const char* C_JAVA_SQL_CONNECTION = "java/sql/Connection"; + JniMethod M_JAVA_SQL_CONNECTION_CLOSE = JniMethod("close", "()V", false); + + // TODO: Provide a "getFullStackTrace" from DocumentDB + //JniMethod M_PLATFORM_UTILS_GET_FULL_STACK_TRACE = JniMethod("getFullStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;", true); + + + /* STATIC STATE. */ + iocc::CriticalSection JVM_LOCK; + iocc::CriticalSection CONSOLE_LOCK; + JniJvm JVM; + bool PRINT_EXCEPTION = false; + std::vector consoleWriteHandlers; + + /* HELPER METHODS. */ + + /** + * Throw exception to Java in case of missing callback pointer. It means that callback is not implemented in + * native platform and Java -> platform operation cannot proceede further. As JniContext is not available at + * this point, we have to obtain exception details from scratch. This is not critical from performance + * perspective because missing handler usually denotes fatal condition. + * + * @param env JNI environment. + */ + int ThrowOnMissingHandler(JNIEnv* env) + { + //jclass cls = env->FindClass(C_PLATFORM_NO_CALLBACK_EXCEPTION); + + //env->ThrowNew(cls, "Callback handler is not set in native platform."); + + return 0; + } + + /** + * Throw generic exception to Java in case of native exception. As JniContext is not available at + * this point, we have to obtain exception details from scratch. This is not critical from performance + * perspective because such exception is usually denotes fatal condition. + * + * @param env JNI environment. + * @param msg Message. + */ + void ThrowToJava(JNIEnv* env, const char* msg) + { + //jclass cls = env->FindClass(C_IGNITE_EXCEPTION); + + //env->ThrowNew(cls, msg); + } + + char* StringToChars(JNIEnv* env, jstring str, int* len) { + if (!str) { + *len = 0; + return NULL; + } + + const char* strChars = env->GetStringUTFChars(str, 0); + const int strCharsLen = env->GetStringUTFLength(str); + + char* strChars0 = new char[strCharsLen + 1]; + std::strcpy(strChars0, strChars); + *(strChars0 + strCharsLen) = 0; + + env->ReleaseStringUTFChars(str, strChars); + + if (len) + *len = strCharsLen; + + return strChars0; + } + + std::string JavaStringToCString(JNIEnv* env, jstring str, int* len) + { + char* resChars = StringToChars(env, str, len); + + if (resChars) + { + std::string res = std::string(resChars, *len); + + delete[] resChars; + + return res; + } + else + return std::string(); + } + + jclass FindClass(JNIEnv* env, const char *name) { + jclass res = env->FindClass(name); + + if (!res) + throw JvmException(); + + jclass res0 = static_cast(env->NewGlobalRef(res)); + + env->DeleteLocalRef(res); + + return res0; + } + + void DeleteClass(JNIEnv* env, jclass cls) { + if (cls) + env->DeleteGlobalRef(cls); + } + + void CheckClass(JNIEnv* env, const char *name) + { + jclass res = env->FindClass(name); + + if (!res) + throw JvmException(); + } + + jmethodID FindMethod(JNIEnv* env, jclass cls, JniMethod mthd) { + jmethodID mthd0 = mthd.isStatic + ? env->GetStaticMethodID(cls, mthd.name, mthd.sign) + : env->GetMethodID(cls, mthd.name, mthd.sign); + + if (!mthd0) + throw JvmException(); + + return mthd0; + } + + jobject NewObject(JNIEnv* env, jclass clazz, jmethodID constructor, ...) { + va_list args; + va_start(args, constructor); + jobject result = env->NewObject(clazz, constructor, args); + va_end(args); + + if (!result) + throw JvmException(); + + return result; + } + + void AddNativeMethod(JNINativeMethod* mthd, JniMethod jniMthd, void* fnPtr) { + mthd->name = jniMthd.name; + mthd->signature = jniMthd.sign; + mthd->fnPtr = fnPtr; + } + + void JniJavaMembers::Initialize(JNIEnv* env) { + c_Class = FindClass(env, C_CLASS); + m_Class_getName = FindMethod(env, c_Class, M_CLASS_GET_NAME); + + c_Throwable = FindClass(env, C_THROWABLE); + m_Throwable_getMessage = FindMethod(env, c_Throwable, M_THROWABLE_GET_MESSAGE); + m_Throwable_printStackTrace = FindMethod(env, c_Throwable, M_THROWABLE_PRINT_STACK_TRACE); + + // TODO: Provide "getFullStackTrace" in DocumentDB + //m_PlatformUtils_getFullStackTrace = FindMethod(env, c_PlatformUtils, M_PLATFORM_UTILS_GET_FULL_STACK_TRACE); + } + + void JniJavaMembers::Destroy(JNIEnv* env) { + DeleteClass(env, c_Class); + DeleteClass(env, c_Throwable); + DeleteClass(env, c_PlatformUtils); + } + + bool JniJavaMembers::WriteErrorInfo(JNIEnv* env, char** errClsName, int* errClsNameLen, char** errMsg, + int* errMsgLen, char** stackTrace, int* stackTraceLen) { + if (env && env->ExceptionCheck()) { + if (m_Class_getName && m_Throwable_getMessage) { + jthrowable err = env->ExceptionOccurred(); + + env->ExceptionClear(); + + jclass errCls = env->GetObjectClass(err); + + jstring clsName = static_cast(env->CallObjectMethod(errCls, m_Class_getName)); + *errClsName = StringToChars(env, clsName, errClsNameLen); + + jstring msg = static_cast(env->CallObjectMethod(err, m_Throwable_getMessage)); + *errMsg = StringToChars(env, msg, errMsgLen); + + jstring trace = NULL; + + if (c_PlatformUtils && m_PlatformUtils_getFullStackTrace) { + trace = static_cast(env->CallStaticObjectMethod(c_PlatformUtils, m_PlatformUtils_getFullStackTrace, err)); + *stackTrace = StringToChars(env, trace, stackTraceLen); + } + + if (errCls) + env->DeleteLocalRef(errCls); + + if (clsName) + env->DeleteLocalRef(clsName); + + if (msg) + env->DeleteLocalRef(msg); + + if (trace) + env->DeleteLocalRef(trace); + + return true; + } + else { + env->ExceptionClear(); + } + } + + return false; + } + + void JniMembers::Initialize(JNIEnv* env) { + c_DocumentDbConnectionProperties = FindClass(env, C_DOCUMENTDB_CONNECTION_PROPERTIES); + m_DocumentDbConnectionPropertiesGetPropertiesFromConnectionString = + FindMethod(env, c_DocumentDbConnectionProperties, M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING); + + c_DocumentDbConnection = FindClass(env, C_DOCUMENTDB_CONNECTION); + //m_DocumentDbConnectionInit = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_PROPERTIES_INIT); + + c_DriverManager = FindClass(env, C_DRIVERMANAGER); + m_DriverManagerGetConnection = FindMethod(env, c_DriverManager, M_DRIVERMANAGER_GET_CONNECTION); + + c_JavaSqlConnection = FindClass(env, C_JAVA_SQL_CONNECTION); + m_JavaSqlConnectionClose = FindMethod(env, c_JavaSqlConnection, M_JAVA_SQL_CONNECTION_CLOSE); + } + + void JniMembers::Destroy(JNIEnv* env) { + DeleteClass(env, c_IgniteException); + DeleteClass(env, c_PlatformIgnition); + DeleteClass(env, c_PlatformTarget); + DeleteClass(env, c_PlatformUtils); + } + + JniJvm::JniJvm() : jvm(NULL), javaMembers(JniJavaMembers()), members(JniMembers()) + { + // No-op. + } + + JniJvm::JniJvm(JavaVM* jvm, JniJavaMembers javaMembers, JniMembers members) : + jvm(jvm), javaMembers(javaMembers), members(members) + { + // No-op. + } + + JavaVM* JniJvm::GetJvm() + { + return jvm; + } + + JniJavaMembers& JniJvm::GetJavaMembers() + { + return javaMembers; + } + + JniMembers& JniJvm::GetMembers() + { + return members; + } + + /** + * Create JVM. + */ + jint GetOrCreateJvm(char** opts, int optsLen, JavaVM** jvm, JNIEnv** env) { + // Check to see if a VM is already created + const jsize nJvms = 1; + jsize nJvmsAvailable = 0; + JavaVM* availableJvms[nJvms]{}; + jint res = JNI_GetCreatedJavaVMs(&availableJvms[0], nJvms, + &nJvmsAvailable); + if (res == JNI_OK && nJvmsAvailable >= 1) { + *jvm = availableJvms[0]; + res = (*jvm)->GetEnv(reinterpret_cast< void** >(env), + JNI_VERSION_1_8); + if (res == JNI_OK) { + return res; + } + } + + // Otherwise, create a VM + JavaVMOption* opts0 = new JavaVMOption[optsLen]; + + for (int i = 0; i < optsLen; i++) + opts0[i].optionString = *(opts + i); + + JavaVMInitArgs args{}; + args.version = JNI_VERSION_1_8; + args.nOptions = optsLen; + args.options = opts0; + args.ignoreUnrecognized = 0; + + res = JNI_CreateJavaVM(jvm, reinterpret_cast(env), &args); + + delete[] opts0; + + return res; + } + + void RegisterNatives(JNIEnv* env) { + { + JNINativeMethod methods[5]; + + int idx = 0; + + // TODO: Investigate registering callbacks to get console and logging streams. + + //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_CONSOLE_WRITE, reinterpret_cast(JniConsoleWrite)); + + //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_LOG, reinterpret_cast(JniLoggerLog)); + //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_IS_LEVEL_ENABLED, reinterpret_cast(JniLoggerIsLevelEnabled)); + + //jint res = env->RegisterNatives(FindClass(env, C_PLATFORM_CALLBACK_UTILS), methods, idx); + + //if (res != JNI_OK) + // throw JvmException(); + } + } + + JniContext::JniContext(JniJvm* jvm, JniHandlers hnds) : jvm(jvm), hnds(hnds) { + // No-op. + } + + JniContext* JniContext::Create(char** opts, int optsLen, JniHandlers hnds) { + return Create(opts, optsLen, hnds, NULL); + } + + void GetJniErrorMessage(std::string& errMsg, jint res) + { + switch (res) + { + case JNI_ERR: + errMsg = "Unknown error (JNI_ERR)."; + break; + + case JNI_EDETACHED: + errMsg = "Thread detached from the JVM."; + break; + + case JNI_EVERSION: + errMsg = "JNI version error."; + break; + + case JNI_ENOMEM: + errMsg = "Could not reserve enough space for object heap. Check Xmx option."; + break; + + case JNI_EEXIST: + errMsg = "JVM already created."; + break; + + case JNI_EINVAL: + errMsg = "Invalid JVM arguments."; + break; + + default: + errMsg = "Unexpected JNI_CreateJavaVM result."; + break; + } + } + + JniContext* JniContext::Create(char** opts, int optsLen, JniHandlers hnds, JniErrorInfo* errInfo) + { + // Acquire global lock to instantiate the JVM. + JVM_LOCK.Enter(); + + // Define local variables. + JavaVM* jvm = NULL; + JNIEnv* env = NULL; + + JniJavaMembers javaMembers; + memset(&javaMembers, 0, sizeof(javaMembers)); + + JniMembers members; + memset(&members, 0, sizeof(members)); + + JniContext* ctx = NULL; + + std::string errClsName; + int errClsNameLen = 0; + std::string errMsg; + int errMsgLen = 0; + std::string stackTrace; + int stackTraceLen = 0; + + try { + if (!JVM.GetJvm()) + { + // 1. Create JVM itself. + jint res = GetOrCreateJvm(opts, optsLen, &jvm, &env); + + if (res == JNI_OK) + { + // 2. Populate members; + javaMembers.Initialize(env); + members.Initialize(env); + + // 3. Register native functions. + RegisterNatives(env); + + // 4. Create JNI JVM. + JVM = JniJvm(jvm, javaMembers, members); + + char* printStack = getenv("IGNITE_CPP_PRINT_STACK"); + PRINT_EXCEPTION = printStack && strcmp("true", printStack) == 0; + } + else + { + GetJniErrorMessage(errMsg, res); + + errMsgLen = static_cast(errMsg.length()); + } + } + + if (JVM.GetJvm()) + ctx = new JniContext(&JVM, hnds); + } + catch (const JvmException&) + { + char* errClsNameChars = NULL; + char* errMsgChars = NULL; + char* stackTraceChars = NULL; + + // Read error info if possible. + javaMembers.WriteErrorInfo(env, &errClsNameChars, &errClsNameLen, &errMsgChars, &errMsgLen, + &stackTraceChars, &stackTraceLen); + + if (errClsNameChars) { + errClsName = errClsNameChars; + + delete[] errClsNameChars; + } + + if (errMsgChars) + { + errMsg = errMsgChars; + + delete[] errMsgChars; + } + + if (stackTraceChars) + { + stackTrace = stackTraceChars; + + delete[] stackTraceChars; + } + + // Destroy mmebers. + if (env) { + members.Destroy(env); + javaMembers.Destroy(env); + } + + // Destroy faulty JVM. + if (jvm) + jvm->DestroyJavaVM(); + } + + // It safe to release the lock at this point. + JVM_LOCK.Leave(); + + // Notify err callback if needed. + if (!ctx) { + if (errInfo) { + JniErrorInfo errInfo0(IGNITE_JNI_ERR_JVM_INIT, errClsName.c_str(), errMsg.c_str()); + + *errInfo = errInfo0; + } + + if (hnds.error) + hnds.error(hnds.target, IGNITE_JNI_ERR_JVM_INIT, errClsName.c_str(), errClsNameLen, + errMsg.c_str(), errMsgLen, stackTrace.c_str(), stackTraceLen, NULL, 0); + } + + return ctx; + } + + int JniContext::Reallocate(int64_t memPtr, int cap) { + JavaVM* jvm = JVM.GetJvm(); + + JNIEnv* env; + + int attachRes = jvm->AttachCurrentThread(reinterpret_cast(&env), NULL); + + if (attachRes == JNI_OK) + AttachHelper::OnThreadAttach(); + else + return -1; + + env->CallStaticVoidMethod(JVM.GetMembers().c_PlatformUtils, JVM.GetMembers().m_PlatformUtils_reallocate, memPtr, cap); + + if (env->ExceptionCheck()) { + env->ExceptionClear(); + + return -1; + } + + return 0; + } + + void JniContext::Detach() { + iocc::Memory::Fence(); + + if (JVM.GetJvm()) { + JNIEnv* env; + + JVM.GetJvm()->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); + + if (env) + JVM.GetJvm()->DetachCurrentThread(); + } + } + + jobject JniContext::DocumentDbConnect(const char* connectionString, + JniErrorInfo* errInfo) { + JNIEnv* env = Attach(); + jstring jConnectionString = + env->NewStringUTF(connectionString); + jobject connection = env->CallStaticObjectMethod( + jvm->GetMembers().c_DriverManager, + jvm->GetMembers().m_DriverManagerGetConnection, jConnectionString); + ExceptionCheck(env, errInfo); + return connection; + } + + void JniContext::DocumentDbDisconnect(const jobject connection, JniErrorInfo* errInfo) { + if (!connection) { + return; + } + JNIEnv* env = Attach(); + env->CallVoidMethod(connection, jvm->GetMembers().m_JavaSqlConnectionClose); + ExceptionCheck(env, errInfo); + env->DeleteLocalRef(connection); + } + + int64_t JniContext::TargetInLongOutLong(jobject obj, int opType, int64_t val, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + int64_t res = env->CallLongMethod(obj, jvm->GetMembers().m_PlatformTarget_inLongOutLong, opType, val); + + ExceptionCheck(env, err); + + return res; + } + + int64_t JniContext::TargetInStreamOutLong(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + int64_t res = env->CallLongMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutLong, opType, memPtr); + + ExceptionCheck(env, err); + + return res; + } + + void JniContext::TargetInStreamOutStream(jobject obj, int opType, int64_t inMemPtr, int64_t outMemPtr, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutStream, opType, inMemPtr, outMemPtr); + + ExceptionCheck(env, err); + } + + jobject JniContext::TargetInStreamOutObject(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObject, opType, memPtr); + + ExceptionCheck(env, err); + + return LocalToGlobal(env, res); + } + + jobject JniContext::TargetInObjectStreamOutObjectStream(jobject obj, int opType, void* arg, int64_t inMemPtr, int64_t outMemPtr, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_inObjectStreamOutObjectStream, opType, arg, inMemPtr, outMemPtr); + + ExceptionCheck(env, err); + + return LocalToGlobal(env, res); + } + + void JniContext::TargetOutStream(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformTarget_outStream, opType, memPtr); + + ExceptionCheck(env, err); + } + + jobject JniContext::TargetOutObject(jobject obj, int opType, JniErrorInfo* err) + { + JNIEnv* env = Attach(); + + jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_outObject, opType); + + ExceptionCheck(env, err); + + return LocalToGlobal(env, res); + } + + void JniContext::TargetInStreamAsync(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + env->CallVoidMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamAsync, opType, memPtr); + + ExceptionCheck(env, err); + } + + jobject JniContext::TargetInStreamOutObjectAsync(jobject obj, int opType, int64_t memPtr, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + jobject res = env->CallObjectMethod(obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObjectAsync, opType, memPtr); + + ExceptionCheck(env, err); + + return LocalToGlobal(env, res); + } + + jobject JniContext::CacheOutOpQueryCursor(jobject obj, int type, int64_t memPtr, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + jobject res = env->CallObjectMethod( + obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObject, type, memPtr); + + ExceptionCheck(env, err); + + return LocalToGlobal(env, res); + } + + jobject JniContext::CacheOutOpContinuousQuery(jobject obj, int type, int64_t memPtr, JniErrorInfo* err) { + JNIEnv* env = Attach(); + + jobject res = env->CallObjectMethod( + obj, jvm->GetMembers().m_PlatformTarget_inStreamOutObject, type, memPtr); + + ExceptionCheck(env, err); + + return LocalToGlobal(env, res); + } + + jobject JniContext::Acquire(jobject obj) + { + if (obj) { + + JNIEnv* env = Attach(); + + jobject obj0 = env->NewGlobalRef(obj); + + ExceptionCheck(env); + + return obj0; + } + + return NULL; + } + + void JniContext::Release(jobject obj) { + if (obj) + { + JavaVM* jvm = JVM.GetJvm(); + + if (jvm) + { + JNIEnv* env; + + jint attachRes = jvm->AttachCurrentThread(reinterpret_cast(&env), NULL); + + if (attachRes == JNI_OK) + { + AttachHelper::OnThreadAttach(); + + env->DeleteGlobalRef(obj); + } + } + } + } + + void JniContext::SetConsoleHandler(ConsoleWriteHandler consoleHandler) { + if (!consoleHandler) + throw std::invalid_argument("consoleHandler can not be null"); + + CONSOLE_LOCK.Enter(); + + consoleWriteHandlers.push_back(consoleHandler); + + CONSOLE_LOCK.Leave(); + } + + int JniContext::RemoveConsoleHandler(ConsoleWriteHandler consoleHandler) { + if (!consoleHandler) + throw std::invalid_argument("consoleHandler can not be null"); + + CONSOLE_LOCK.Enter(); + + int oldSize = static_cast(consoleWriteHandlers.size()); + + consoleWriteHandlers.erase(remove(consoleWriteHandlers.begin(), consoleWriteHandlers.end(), + consoleHandler), consoleWriteHandlers.end()); + + int removedCnt = oldSize - static_cast(consoleWriteHandlers.size()); + + CONSOLE_LOCK.Leave(); + + return removedCnt; + } + + void JniContext::ThrowToJava(char* msg) { + JNIEnv* env = Attach(); + + env->ThrowNew(jvm->GetMembers().c_IgniteException, msg); + } + + void JniContext::DestroyJvm() { + jvm->GetJvm()->DestroyJavaVM(); + } + + /** + * Attach thread to JVM. + */ + JNIEnv* JniContext::Attach() { + JNIEnv* env; + + jint attachRes = jvm->GetJvm()->AttachCurrentThread(reinterpret_cast(&env), NULL); + + if (attachRes == JNI_OK) + AttachHelper::OnThreadAttach(); + else { + if (hnds.error) + hnds.error(hnds.target, IGNITE_JNI_ERR_JVM_ATTACH, NULL, 0, NULL, 0, NULL, 0, NULL, 0); + } + + return env; + } + + void JniContext::ExceptionCheck(JNIEnv* env) { + ExceptionCheck(env, NULL); + } + + void JniContext::ExceptionCheck(JNIEnv* env, JniErrorInfo* errInfo) + { + if (env->ExceptionCheck()) { + jthrowable err = env->ExceptionOccurred(); + + if (PRINT_EXCEPTION) + env->CallVoidMethod(err, jvm->GetJavaMembers().m_Throwable_printStackTrace); + + env->ExceptionClear(); + + // Get error class name and message. + jclass cls = env->GetObjectClass(err); + + jstring clsName = static_cast(env->CallObjectMethod(cls, jvm->GetJavaMembers().m_Class_getName)); + jstring msg = static_cast(env->CallObjectMethod(err, jvm->GetJavaMembers().m_Throwable_getMessage)); + int traceLen = 0; + std::string trace0 = ""; + if (jvm->GetJavaMembers().c_PlatformUtils + && jvm->GetJavaMembers() + .m_PlatformUtils_getFullStackTrace) { + jstring trace = static_cast< jstring >( + env->CallStaticObjectMethod( + jvm->GetJavaMembers().c_PlatformUtils, + jvm->GetJavaMembers() + .m_PlatformUtils_getFullStackTrace, + err)); + + trace0 = + JavaStringToCString(env, trace, &traceLen); + } + + env->DeleteLocalRef(cls); + + int clsNameLen; + std::string clsName0 = JavaStringToCString(env, clsName, &clsNameLen); + + int msgLen; + std::string msg0 = JavaStringToCString(env, msg, &msgLen); + + if (errInfo) + { + JniErrorInfo errInfo0(IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), msg0.c_str()); + + *errInfo = errInfo0; + } + + // Get error additional data (if any). + jbyteArray errData = nullptr; + if (jvm->GetMembers().c_PlatformUtils + && jvm->GetMembers().m_PlatformUtils_errData) { + errData = static_cast< jbyteArray >( + env->CallStaticObjectMethod( + jvm->GetMembers().c_PlatformUtils, + jvm->GetMembers().m_PlatformUtils_errData, + err)); + } + + if (errData) + { + jbyte* errBytesNative = env->GetByteArrayElements(errData, NULL); + + int errBytesLen = env->GetArrayLength(errData); + + if (hnds.error) + hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(), + msgLen, trace0.c_str(), traceLen, errBytesNative, errBytesLen); + + env->ReleaseByteArrayElements(errData, errBytesNative, JNI_ABORT); + } + else + { + if (hnds.error) + hnds.error(hnds.target, IGNITE_JNI_ERR_GENERIC, clsName0.c_str(), clsNameLen, msg0.c_str(), + msgLen, trace0.c_str(), traceLen, NULL, 0); + } + + env->DeleteLocalRef(err); + } + } + + /** + * Convert local reference to global. + */ + jobject JniContext::LocalToGlobal(JNIEnv* env, jobject localRef) { + if (localRef) { + jobject globalRef = env->NewGlobalRef(localRef); + + env->DeleteLocalRef(localRef); // Clear local ref irrespective of result. + + if (!globalRef) + ExceptionCheck(env); + + return globalRef; + } + else + return NULL; + } + + JNIEXPORT void JNICALL JniConsoleWrite(JNIEnv *env, jclass, jstring str, jboolean isErr) { + CONSOLE_LOCK.Enter(); + + if (consoleWriteHandlers.size() > 0) { + ConsoleWriteHandler consoleWrite = consoleWriteHandlers.at(0); + + const char* strChars = env->GetStringUTFChars(str, 0); + const int strCharsLen = env->GetStringUTFLength(str); + + consoleWrite(strChars, strCharsLen, isErr); + + env->ReleaseStringUTFChars(str, strChars); + } + + CONSOLE_LOCK.Leave(); + } + + JNIEXPORT void JNICALL JniLoggerLog(JNIEnv *env, jclass, jlong envPtr, jint level, jstring message, jstring category, jstring errorInfo, jlong memPtr) { + int messageLen; + char* messageChars = StringToChars(env, message, &messageLen); + + int categoryLen; + char* categoryChars = StringToChars(env, category, &categoryLen); + + int errorInfoLen; + char* errorInfoChars = StringToChars(env, errorInfo, &errorInfoLen); + + IGNITE_SAFE_PROC(env, envPtr, LoggerLogHandler, loggerLog, level, messageChars, messageLen, categoryChars, categoryLen, errorInfoChars, errorInfoLen, memPtr); + + if (messageChars) + delete[] messageChars; + + if (categoryChars) + delete[] categoryChars; + + if (errorInfoChars) + delete[] errorInfoChars; + } + + JNIEXPORT jboolean JNICALL JniLoggerIsLevelEnabled(JNIEnv *env, jclass, jlong envPtr, jint level) { + IGNITE_SAFE_FUNC(env, envPtr, LoggerIsLevelEnabledHandler, loggerIsLevelEnabled, level); + } + + JNIEXPORT jlong JNICALL JniInLongOutLong(JNIEnv *env, jclass, jlong envPtr, jint type, jlong val) { + IGNITE_SAFE_FUNC(env, envPtr, InLongOutLongHandler, inLongOutLong, type, val); + } + + JNIEXPORT jlong JNICALL JniInLongLongLongObjectOutLong(JNIEnv *env, jclass, jlong envPtr, jint type, jlong val1, jlong val2, jlong val3, jobject arg) { + IGNITE_SAFE_FUNC(env, envPtr, InLongLongLongObjectOutLongHandler, inLongLongLongObjectOutLong, type, val1, val2, val3, arg); + } + } // namespace java + } // namespace jni + } // namespace odbc +} // namespace ignite diff --git a/src/odbc/src/jni/os/linux/utils.cpp b/src/odbc/src/jni/os/linux/utils.cpp new file mode 100644 index 000000000..6fd4d6e7a --- /dev/null +++ b/src/odbc/src/jni/os/linux/utils.cpp @@ -0,0 +1,432 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include + +#include +#include +#include +#include +#include + +#include "ignite/common/utils.h" +#include "ignite/common/fixed_size_array.h" + +#include "ignite/odbc/jni/utils.h" +#include "ignite/odbc/jni/java.h" + +using namespace ignite::common; +using namespace ignite::odbc::jni::java; + +namespace ignite +{ + namespace odbc { + namespace jni { + const char* JAVA_HOME = "JAVA_HOME"; + const char* JAVA_DLL1 = "/jre/lib/amd64/server/libjvm.so"; + const char* JAVA_DLL2 = "/lib/server/libjvm.so"; + const char* JAVA_DLL_DARWIN = "libjvm.dylib"; + + const char* DOCUMENTDB_HOME = "DOCUMENTDB_HOME"; + + const char* IGNITE_NATIVE_TEST_CLASSPATH = "IGNITE_NATIVE_TEST_CLASSPATH"; + + /** Excluded modules from test classpath. */ + const char* TEST_EXCLUDED_MODULES[] = {"rest-http"}; + + /** Key indicating that the thread is attached. */ + static pthread_key_t attachKey; + + /** Helper to ensure that attach key is allocated only once. */ + static pthread_once_t attachKeyInit = PTHREAD_ONCE_INIT; + + void DestroyAttachKey(void* key) { + delete reinterpret_cast< AttachHelper* >(key); + } + + void AllocateAttachKey() { + pthread_key_create(&attachKey, DestroyAttachKey); + } + + AttachHelper::~AttachHelper() { + JniContext::Detach(); + } + + void AttachHelper::OnThreadAttach() { + pthread_once(&attachKeyInit, AllocateAttachKey); + + void* val = pthread_getspecific(attachKey); + + if (!val) + pthread_setspecific(attachKey, new AttachHelper()); + } + + /** + * Checks if the path looks like binary release home directory. + * Internally checks for presence of some directories, that are + * @return @c true if the path looks like binary release home directory. + */ + bool LooksLikeBinaryReleaseHome(const std::string& path) { + static const char* PROBE_CORE_LIB = "/libs/ignite-core*.jar"; + + std::string coreLibProbe = path + PROBE_CORE_LIB; + + return FileExists(coreLibProbe); + } + + /** + * Checks if the path looks like source release home directory. + * Internally checks for presence of core source directory. + * @return @c true if the path looks like binary release home directory. + */ + bool LooksLikeSourceReleaseHome(const std::string& path) { + static const char* PROBE_CORE_SOURCE = + "/modules/core/src/main/java/org/apache/ignite"; + + std::string coreSourcePath = path + PROBE_CORE_SOURCE; + + return IsValidDirectory(coreSourcePath); + } + + /** + * Helper function for Ignite home resolution. + * Goes upwards in directory hierarchy and checks whether certain + * folders exist in the path. + * + * @param path Path to evaluate. + * @return res Resolved directory. Empty string if not found. + */ + std::string ResolveIgniteHome0(const std::string& path) { + if (!IsValidDirectory(path)) + return std::string(); + + // Remove trailing slashes, otherwise we will have an infinite loop. + size_t last = path.find_last_not_of("/ "); + + if (last == std::string::npos) + return std::string(); + + std::string path0(path, 0, last + 1); + + if (LooksLikeBinaryReleaseHome(path0) || LooksLikeSourceReleaseHome(path0)) + return path0; + + // Evaluate parent directory. + size_t slashPos = path0.find_last_of("/"); + + if (slashPos == std::string::npos) + return std::string(); + + std::string parent(path0, 0, slashPos); + + return ResolveIgniteHome0(parent); + } + + /** + * Create classpath picking JARs from the given path. + * + * @path Path. + * @return Classpath; + */ + std::string ClasspathJars(const std::string& path) { + std::string res; + + DIR* dir = opendir(path.c_str()); + + if (dir) { + struct dirent* entry; + + while ((entry = readdir(dir)) != NULL) { + char* dot = strrchr(entry->d_name, '.'); + if (dot && !strcmp(dot, ".jar")) { + res.append(path); + res.append("/"); + res.append(entry->d_name); + res.append(":"); + } + } + + closedir(dir); + } + + return res; + } + + /** + * Check if path corresponds to excluded module. + * + * @path Path. + * @return True if path should be excluded. + */ + bool IsExcludedModule(const std::string& path) { + std::string lower_path = path; + std::transform(path.begin(), path.end(), lower_path.begin(), ::tolower); + + for (size_t i = 0; i < sizeof(TEST_EXCLUDED_MODULES) / sizeof(char*); i++) { + if (lower_path.find(TEST_EXCLUDED_MODULES[i]) != std::string::npos) + return true; + } + + return false; + } + + /** + * Create classpath picking compiled classes from the given path. + * + * @path Path. + * @return Classpath; + */ + std::string ClasspathExploded(const std::string& path, bool down) { + std::string res; + + if (FileExists(path) && !IsExcludedModule(path)) { + // 1. Append "target\classes". + std::string classesPath = path + "/target/classes"; + + if (FileExists(classesPath)) { + res += classesPath; + res += ":"; + } + + // 2. Append "target\test-classes" + std::string testClassesPath = path + "/target/test-classes"; + + if (FileExists(testClassesPath)) { + res += testClassesPath; + res += ":"; + } + + // 3. Append "target\libs" + std::string libsPath = path + "/target/libs"; + + if (FileExists(libsPath)) { + std::string libsCp = ClasspathJars(libsPath); + res += libsCp; + } + + // 4. Do the same for child if needed. + if (down) { + DIR* dir = opendir(path.c_str()); + + if (dir) { + struct dirent* entry; + + while ((entry = readdir(dir)) != NULL) { + std::string entryPath = entry->d_name; + + if (entryPath.compare(".") != 0 + && entryPath.compare("..") != 0) { + std::string entryFullPath = path + "/" + entryPath; + + struct stat entryFullStat; + + if (stat(entryFullPath.c_str(), &entryFullStat) != -1 + && S_ISDIR(entryFullStat.st_mode)) { + std::string childCp = + ClasspathExploded(entryFullPath, false); + + res += childCp; + } + } + } + + closedir(dir); + } + } + } + + return res; + } + + std::string CreateDocumentDbHomeClasspath(const std::string& home, bool forceTest) { + std::string res = std::string(); + + // 1. Add exploded test directories. + if (forceTest) { + std::string examplesPath = home + "/examples"; + std::string examplesCp = ClasspathExploded(examplesPath, true); + res.append(examplesCp); + + std::string modulesPath = home + "/modules"; + std::string modulesCp = ClasspathExploded(modulesPath, true); + res.append(modulesCp); + } + + // 2. Add regular jars from "libs" folder excluding "optional". + std::string libsPath = home + "/libs"; + + if (FileExists(libsPath)) { + res.append(ClasspathJars(libsPath)); + + // Append inner directories. + DIR* dir = opendir(libsPath.c_str()); + + if (dir) { + struct dirent* entry; + + while ((entry = readdir(dir)) != NULL) { + std::string entryPath = entry->d_name; + + if (entryPath.compare(".") != 0 && entryPath.compare("..") != 0 + && entryPath.compare("optional") != 0) { + std::string entryFullPath = libsPath; + + entryFullPath.append("/"); + entryFullPath.append(entryPath); + + struct stat entryFullStat; + + if (stat(entryFullPath.c_str(), &entryFullStat) != -1 + && S_ISDIR(entryFullStat.st_mode)) + res.append(ClasspathJars(entryFullPath)); + } + } + + closedir(dir); + } + } + + // 3. Return. + return res; + } + + std::string FindJvmLibrary(const std::string& path) { + #ifdef __APPLE__ + return JAVA_DLL_DARWIN; + #else + // If path is provided explicitly, then check only it. + if (!path.empty() && FileExists(path)) + return path; + + std::string javaEnv = GetEnv(JAVA_HOME); + + if (!javaEnv.empty()) { + std::string javaDll = javaEnv + JAVA_DLL1; + + if (FileExists(javaDll)) + return javaDll; + + javaDll = javaEnv + JAVA_DLL2; + + if (FileExists(javaDll)) + return javaDll; + } + + return std::string(); + #endif + } + + bool LoadJvmLibrary(const std::string& path) { + #ifdef __APPLE__ + return RTLD_DEFAULT; + #else + void* hnd = dlopen(path.c_str(), RTLD_LAZY); + + return hnd != NULL; + #endif + } + + /** + * Create Ignite classpath based on user input and home directory. + * + * @param usrCp User's classpath. + * @param home Ignite home directory. + * @param forceTest Whether test classpath must be used. + * @return Classpath. + */ + std::string CreateIgniteClasspath(const std::string& usrCp, + const std::string* home, bool forceTest) { + // 1. Append user classpath if it exists. + std::string cp; + + if (!usrCp.empty()) { + cp.append(usrCp); + + if (*cp.rbegin() != ';') + cp.push_back(';'); + } + + // 2. Append home classpath if home is defined. + if (home) { + std::string homeCp = CreateDocumentDbHomeClasspath(*home, forceTest); + + cp.append(homeCp); + } + + // 3. Return. + return cp; + } + + /** + * Adds semicolon at the end of the path if needed. + * @param usrCp Classpath provided by user. + * @return Normalized classpath. + */ + std::string NormalizeClasspath(const std::string& usrCp) { + if (usrCp.empty() || *usrCp.rbegin() == ';') + return usrCp; + + return usrCp + ';'; + } + + std::string CreateDocumentDbClasspath(const std::string& usrCp, + const std::string& home) { + // 1. Append user classpath if it exists. + std::string cp = NormalizeClasspath(usrCp); + + // 2. Append home classpath + if (!home.empty()) { + std::string env = GetEnv(IGNITE_NATIVE_TEST_CLASSPATH, "false"); + + bool forceTest = ToLower(env) == "true"; + + std::string homeCp = CreateDocumentDbHomeClasspath(home, forceTest); + + cp.append(homeCp); + } + + // 3. Return. + return cp; + } + + std::string ResolveDocumentDbHome(const std::string& path) { + // 1. Check passed argument. + if (IsValidDirectory(path)) + return path; + + // 2. Check environment variable. + std::string home = GetEnv(DOCUMENTDB_HOME); + + if (IsValidDirectory(home)) + return home; + + // 3. Check current work dir. + FixedSizeArray< char > curDir(1024 * 16); + + char* res = getcwd(curDir.GetData(), curDir.GetSize()); + + if (!res) + return std::string(); + + std::string curDirStr(curDir.GetData()); + + return ResolveIgniteHome0(curDirStr); + } + } // namespace jni + } // namespace odbc +} diff --git a/src/odbc/src/jni/os/win/utils.cpp b/src/odbc/src/jni/os/win/utils.cpp new file mode 100644 index 000000000..e41fb56af --- /dev/null +++ b/src/odbc/src/jni/os/win/utils.cpp @@ -0,0 +1,459 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "ignite/common/concurrent.h" +#include "ignite/common/utils.h" +#include "ignite/common/fixed_size_array.h" + +#include "ignite/odbc/jni/utils.h" +#include "ignite/odbc/jni/java.h" + +using namespace ignite::common; +using namespace ignite::common::concurrent; + +using namespace ignite::odbc::jni::java; + +namespace ignite +{ + namespace odbc + { + namespace jni + { + const char* JAVA_HOME = "JAVA_HOME"; + const char* JAVA_DLL1 = "\\jre\\bin\\server\\jvm.dll"; + const char* JAVA_DLL2 = "\\bin\\server\\jvm.dll"; + + const char* DOCUMENTDB_HOME = "DOCUMENTDB_HOME"; + + const char* IGNITE_NATIVE_TEST_CLASSPATH = "IGNITE_NATIVE_TEST_CLASSPATH"; + + /** Excluded modules from test classpath. */ + const char* TEST_EXCLUDED_MODULES[] = { "rest-http" }; + + AttachHelper::~AttachHelper() + { + // No-op. + } + + void AttachHelper::OnThreadAttach() + { + // No-op. + } + + /** + * Checks if the path looks like binary release home directory. + * Internally checks for presence of core library. + * @return @c true if the path looks like binary release home directory. + */ + bool LooksLikeBinaryReleaseHome(const std::string& path) + { + static const char* PROBE_CORE_LIB = "\\libs\\ignite-core*.jar"; + + std::string coreLibProbe = path + PROBE_CORE_LIB; + + return FileExists(coreLibProbe); + } + + /** + * Checks if the path looks like source release home directory. + * Internally checks for presence of core source directory. + * @return @c true if the path looks like binary release home directory. + */ + bool LooksLikeSourceReleaseHome(const std::string& path) + { + static const char* PROBE_CORE_SOURCE = "\\modules\\core\\src\\main\\java\\org\\apache\\ignite"; + + std::string coreSourcePath = path + PROBE_CORE_SOURCE; + + return IsValidDirectory(coreSourcePath); + } + + /** + * Helper function for Ignite home resolution. + * Goes upwards in directory hierarchy and checks whether certain + * folders exist in the path. + * + * @param path Path to evaluate. + * @return res Resolved directory. Empty string if not found. + */ + std::string ResolveIgniteHome0(const std::string& path) + { + if (!IsValidDirectory(path)) + return std::string(); + + // Remove trailing slashes, otherwise we will have an infinite loop. + size_t last = path.find_last_not_of("/\\ "); + + if (last == std::string::npos) + return std::string(); + + std::string path0(path, 0, last + 1); + + if (LooksLikeBinaryReleaseHome(path0) || LooksLikeSourceReleaseHome(path0)) + return path0; + + // Evaluate parent directory. + size_t slashPos = path0.find_last_of("/\\"); + + if (slashPos == std::string::npos) + return std::string(); + + std::string parent(path0, 0, slashPos); + + return ResolveIgniteHome0(parent); + } + + /** + * Create classpath picking JARs from the given path. + * + * @path Path. + * @return Classpath; + */ + std::string ClasspathJars(const std::string& path) + { + std::string searchPath = path + "\\*.jar"; + + WIN32_FIND_DATAA findData; + + HANDLE hnd = FindFirstFileA(searchPath.c_str(), &findData); + + if (hnd == INVALID_HANDLE_VALUE) + return std::string(); + + std::string res; + + do + { + res.append(path); + res.append("\\"); + res.append(findData.cFileName); + res.append(";"); + } while (FindNextFileA(hnd, &findData) != 0); + + FindClose(hnd); + + return res; + } + + /** + * Check if path corresponds to excluded module. + * + * @path Path. + * @return True if path should be excluded. + */ + bool IsExcludedModule(const std::string& path) { + std::string lower_path = path; + std::transform(path.begin(), path.end(), lower_path.begin(), ::tolower); + + for (size_t i = 0; i < sizeof(TEST_EXCLUDED_MODULES) / sizeof(char*); i++) { + if (lower_path.find(TEST_EXCLUDED_MODULES[i]) != std::string::npos) + return true; + } + + return false; + } + + /** + * Create classpath picking compiled classes from the given path. + * + * @path Path. + * @return Classpath; + */ + std::string ClasspathExploded(const std::string& path, bool down) + { + std::string res; + + if (FileExists(path) && !IsExcludedModule(path)) + { + // 1. Append "target\classes". + std::string classesPath = path + "\\target\\classes"; + + if (FileExists(classesPath)) { + res.append(classesPath); + res.append(";"); + } + + // 2. Append "target\test-classes" + std::string testClassesPath = path + "\\target\\test-classes"; + + if (FileExists(testClassesPath)) { + res.append(testClassesPath); + res.append(";"); + } + + // 3. Append "target\libs" + std::string libsPath = path + "\\target\\libs"; + + if (FileExists(libsPath)) { + std::string libsCp = ClasspathJars(libsPath); + res.append(libsCp); + } + + // 4. Do the same for child if needed. + if (down) + { + std::string searchPath = path + "\\*"; + + WIN32_FIND_DATAA findData; + + HANDLE hnd = FindFirstFileA(searchPath.c_str(), &findData); + + if (hnd != INVALID_HANDLE_VALUE) + { + do + { + if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + std::string childPath = findData.cFileName; + + if (childPath.compare(".") != 0 && + childPath.compare("..") != 0) + { + std::string childCp = + ClasspathExploded(path + "\\" + childPath, false); + + res.append(childCp); + } + } + } while (FindNextFileA(hnd, &findData) != 0); + + FindClose(hnd); + } + } + } + + return res; + } + + std::string CreateDocumentDbHomeClasspath(const std::string& home, bool forceTest) + { + std::string res; + + // 1. Add exploded test directories. + if (forceTest) + { + std::string examplesPath = home + "\\examples"; + std::string examplesCp = ClasspathExploded(examplesPath, true); + res.append(examplesCp); + + std::string modulesPath = home + "\\modules"; + std::string modulesCp = ClasspathExploded(modulesPath, true); + res.append(modulesCp); + } + + // 2. Add regular jars from "libs" folder excluding "optional". + std::string libsPath = home + "\\libs"; + + if (FileExists(libsPath)) + { + res.append(ClasspathJars(libsPath)); + + // Append inner directories. + std::string libsSearchPath = libsPath + "\\*"; + + WIN32_FIND_DATAA libsFindData; + + HANDLE libsHnd = FindFirstFileA(libsSearchPath.c_str(), &libsFindData); + + if (libsHnd != INVALID_HANDLE_VALUE) + { + do + { + if (libsFindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + std::string libsChildPath = libsFindData.cFileName; + + if (libsChildPath.compare(".") != 0 && + libsChildPath.compare("..") != 0 && + libsChildPath.compare("optional") != 0) { + std::string libsFolder = libsPath + "\\" + libsChildPath; + + res.append(ClasspathJars(libsFolder)); + } + } + } while (FindNextFileA(libsHnd, &libsFindData) != 0); + + FindClose(libsHnd); + } + } + + // 3. Return. + return res; + } + + std::string FindJvmLibrary(const std::string& path) + { + // If path is provided explicitly, then check only it. + if (!path.empty() && FileExists(path)) + return path; + + std::string javaEnv = GetEnv(JAVA_HOME); + + if (!javaEnv.empty()) + { + std::string javaDll = javaEnv + JAVA_DLL1; + + if (FileExists(javaDll)) + return javaDll; + + javaDll = javaEnv + JAVA_DLL2; + + if (FileExists(javaDll)) + return javaDll; + } + + return std::string(); + } + + bool LoadJvmLibrary(const std::string& path) + { + HMODULE mod = LoadLibraryA(path.c_str()); + + return mod != NULL; + } + + /** + * Create Ignite classpath based on user input and home directory. + * + * @param usrCp User's classpath. + * @param home Ignite home directory. + * @param forceTest Whether test classpath must be used. + * @return Classpath. + */ + std::string CreateIgniteClasspath(const std::string& usrCp, const std::string* home, bool forceTest) + { + // 1. Append user classpath if it exists. + std::string cp; + + if (!usrCp.empty()) + { + cp.append(usrCp); + + if (*cp.rbegin() != ';') + cp.push_back(';'); + } + + // 2. Append home classpath if home is defined. + if (home) + { + std::string homeCp = CreateDocumentDbHomeClasspath(*home, forceTest); + + cp.append(homeCp); + } + + // 3. Return. + return cp; + } + + /** + * Adds semicolon at the end of the path if needed. + * @param usrCp Classpath provided by user. + * @return Normalized classpath. + */ + std::string NormalizeClasspath(const std::string& usrCp) + { + if (usrCp.empty() || *usrCp.rbegin() == ';') + return usrCp; + + return usrCp + ';'; + } + + std::string CreateDocumentDbClasspath(const std::string& usrCp, const std::string& home) + { + // 1. Append user classpath if it exists. + std::string cp = NormalizeClasspath(usrCp); + + // 2. Append home classpath + if (!home.empty()) + { + std::string env = GetEnv(IGNITE_NATIVE_TEST_CLASSPATH, "false"); + + bool forceTest = ToLower(env) == "true"; + + std::string homeCp = CreateDocumentDbHomeClasspath(home, forceTest); + + cp.append(homeCp); + } + + // 3. Return. + return cp; + } + + std::string ResolveDocumentDbHome(const std::string& path) + { + // 1. Check passed argument. + if (IsValidDirectory(path)) + return path; + + // 2. Check environment variable. + std::string home = GetEnv(DOCUMENTDB_HOME); + + if (IsValidDirectory(home)) + return home; + + // 3. Check current work dir. + DWORD curDirLen = GetCurrentDirectoryA(0, NULL); + + if (!curDirLen) + return std::string(); + + FixedSizeArray curDir(curDirLen); + + curDirLen = GetCurrentDirectoryA(curDir.GetSize(), curDir.GetData()); + + if (!curDirLen) + return std::string(); + + std::string curDirStr(curDir.GetData()); + + return ResolveIgniteHome0(curDirStr); + } + } // jni + } // odbc +} // ignite + +BOOL WINAPI DllMain(_In_ HINSTANCE hinstDLL, _In_ DWORD fdwReason, _In_ LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + if (!ThreadLocal::OnProcessAttach()) + return FALSE; + + break; + + case DLL_THREAD_DETACH: + ThreadLocal::OnThreadDetach(); + + JniContext::Detach(); + + break; + + case DLL_PROCESS_DETACH: + ThreadLocal::OnProcessDetach(); + + break; + + default: + break; + } + + return TRUE; +} \ No newline at end of file diff --git a/src/odbc/src/log.cpp b/src/odbc/src/log.cpp index 755798f48..80f0b8b88 100644 --- a/src/odbc/src/log.cpp +++ b/src/odbc/src/log.cpp @@ -67,7 +67,7 @@ namespace ignite { if (IsEnabled()) { - ignite::common::concurrent::CsLockGuard guard(mutex); + common::concurrent::CsLockGuard guard(mutex); stream << message << std::endl; } } diff --git a/src/odbc/src/protocol_version.cpp b/src/odbc/src/protocol_version.cpp index a073ab26c..f196b33e7 100644 --- a/src/odbc/src/protocol_version.cpp +++ b/src/odbc/src/protocol_version.cpp @@ -17,7 +17,7 @@ #include -#include +#include #include "ignite/odbc/protocol_version.h" #include "ignite/odbc/utility.h" diff --git a/src/odbc/src/ssl_mode.cpp b/src/odbc/src/ssl_mode.cpp index 70fd05891..0f5aba861 100644 --- a/src/odbc/src/ssl_mode.cpp +++ b/src/odbc/src/ssl_mode.cpp @@ -15,7 +15,7 @@ * limitations under the License. */ -#include +#include #include "ignite/odbc/ssl_mode.h" diff --git a/src/odbc/src/utility.cpp b/src/odbc/src/utility.cpp index c060a0ada..8ac9221f7 100644 --- a/src/odbc/src/utility.cpp +++ b/src/odbc/src/utility.cpp @@ -67,7 +67,7 @@ namespace ignite writer.WriteString(str.data(), static_cast(str.size())); } - void ReadDecimal(ignite::impl::binary::BinaryReaderImpl& reader, common::Decimal& decimal) + void ReadDecimal(ignite::impl::binary::BinaryReaderImpl& reader, odbc::common::Decimal& decimal) { int8_t hdr = reader.ReadInt8(); @@ -94,20 +94,20 @@ namespace ignite sign = -1; } - common::Decimal res(mag.data(), static_cast(mag.size()), scale, sign); + odbc::common::Decimal res(mag.data(), static_cast(mag.size()), scale, sign); decimal.Swap(res); } - void WriteDecimal(ignite::impl::binary::BinaryWriterImpl& writer, const common::Decimal& decimal) + void WriteDecimal(ignite::impl::binary::BinaryWriterImpl& writer, const odbc::common::Decimal& decimal) { writer.WriteInt8(ignite::impl::binary::IGNITE_TYPE_DECIMAL); - const common::BigInteger &unscaled = decimal.GetUnscaledValue(); + const odbc::common::BigInteger &unscaled = decimal.GetUnscaledValue(); writer.WriteInt32(decimal.GetScale()); - common::FixedSizeArray magnitude; + odbc::common::FixedSizeArray magnitude; unscaled.MagnitudeToBytes(magnitude); From e9ed8f533dd9acaafb0447428cad7f7ca4ec00db Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 27 Jan 2022 12:04:09 -0800 Subject: [PATCH 089/165] [AD-522] resolve errors after merging develop branch * GetAddresses() is deprecated, replaced it with GetHostname() and GetTcpPort() to get hostname and port number, respectively. * replaced GetSchema() with GetSchemaName() * removed commented out code * refactor with dsn_configuration_window.cpp --- .../system/ui/dsn_configuration_window.cpp | 4 +- src/odbc/src/connection.cpp | 48 ++----------------- 2 files changed, 5 insertions(+), 47 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 06b77c3b3..ec6086aa6 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -221,7 +221,7 @@ namespace ignite int DsnConfigurationWindow::CreateSshSettingsGroup(int posX, int posY, int sizeX) { - enum { LABEL_WIDTH = 120 }; + enum { LABEL_WIDTH = 120 }; int labelPosX = posX + INTERVAL; @@ -417,8 +417,6 @@ namespace ignite int DsnConfigurationWindow::CreateAdditionalSettingsGroup(int posX, int posY, int sizeX) { enum { LABEL_WIDTH = 120 }; // same as SSH settings - //enum { LABEL_WIDTH = 130 }; // -AL- different definition from above. I can also - // change it to the same int labelPosX = posX + INTERVAL; diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index 4bdc511f7..8367669e0 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -522,24 +522,6 @@ namespace ignite SqlResult::Type Connection::MakeRequestHandshake() { - /* ProtocolVersion protocolVersion = config.GetProtocolVersion(); - - if (!protocolVersion.IsSupported()) - { - AddStatusRecord(SqlState::S01S00_INVALID_CONNECTION_STRING_ATTRIBUTE, - "Protocol version is not supported: " + protocolVersion.ToString()); - - return SqlResult::AI_ERROR; - } - - if (protocolVersion < ProtocolVersion::VERSION_2_5_0 && !config.GetUser().empty()) - { - AddStatusRecord(SqlState::S01S00_INVALID_CONNECTION_STRING_ATTRIBUTE, - "Authentication is not allowed for protocol version below 2.5.0"); - - return SqlResult::AI_ERROR; - } - */ HandshakeRequest req(config); HandshakeResponse rsp; @@ -582,13 +564,6 @@ namespace ignite if (!rsp.GetError().empty()) constructor << "Additional info: " << rsp.GetError() << " "; - /* constructor - << "Current version of the protocol, used by the server " - "node is " - << rsp.GetCurrentVer().ToString() << ", " - << "driver protocol version introduced in version " - << protocolVersion.ToString() << "."; */ - AddStatusRecord(SqlState::S08004_CONNECTION_REJECTED, constructor.str()); return SqlResult::AI_ERROR; @@ -667,9 +642,9 @@ namespace ignite std::string Connection::FormatJdbcConnectionString() const { std::string host = "localhost"; std::string port = "27017"; - if (!config.GetAddresses().empty()) { - host = config.GetAddresses()[0].host; - port = std::to_string(config.GetAddresses()[0].port); + if (!config.GetHostname().empty()) { + host = config.GetHostname(); + port = std::to_string(config.GetTcpPort()); } std::string jdbConnectionString; @@ -678,7 +653,7 @@ namespace ignite jdbConnectionString.append(":" + config.GetPassword()); jdbConnectionString.append("@" + host); jdbConnectionString.append(":" + port); - jdbConnectionString.append("/" + config.GetSchema()); + jdbConnectionString.append("/" + config.GetSchemaName()); jdbConnectionString.append("?tlsAllowInvalidHostnames=true"); // Check if internal SSH tunnel should be enabled. @@ -778,21 +753,6 @@ namespace ignite LOG_MSG("'Address' is not set. Using legacy connection method."); endPoints.push_back(EndPoint(cfg.GetHostname(), cfg.GetTcpPort())); return; - - /*if (!cfg.IsAddressesSet()) - { - LOG_MSG("'Address' is not set. Using legacy connection method."); - - endPoints.push_back(EndPoint(cfg.GetHostname(), cfg.GetTcpPort())); - - return; - } - - endPoints = cfg.GetAddresses(); - - - std::random_shuffle(endPoints.begin(), endPoints.end()); - */ } int32_t Connection::RetrieveTimeout(void* value) From 4fa885174a501a4a674e60d781f5995e27ee798c Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Thu, 27 Jan 2022 13:32:28 -0800 Subject: [PATCH 090/165] [AD-512] Resolve issue with missing include file. --- src/odbc/include/ignite/odbc/connection.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/odbc/include/ignite/odbc/connection.h b/src/odbc/include/ignite/odbc/connection.h index 0a917a50d..f5175f04a 100644 --- a/src/odbc/include/ignite/odbc/connection.h +++ b/src/odbc/include/ignite/odbc/connection.h @@ -28,6 +28,7 @@ #include "ignite/odbc/config/connection_info.h" #include "ignite/odbc/config/configuration.h" #include "ignite/odbc/diagnostic/diagnosable_adapter.h" +#include "ignite/odbc/end_point.h" #include "ignite/odbc/streaming/streaming_context.h" #include "ignite/odbc/odbc_error.h" #include "ignite/odbc/jni/java.h" @@ -511,7 +512,7 @@ namespace ignite * @param cfg Configuration. * @param endPoints End points. */ - static void CollectAddresses(const config::Configuration& cfg, std::vector& endPoints); + static void CollectAddresses(const config::Configuration& cfg, std::vector< EndPoint >& endPoints); /** * Retrieve timeout from parameter. From 66333de102af2d3d6724f400d3cba71ff2dc6a75 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 27 Jan 2022 15:32:57 -0800 Subject: [PATCH 091/165] [AD-522] make BoolParseResult recognizable --- src/odbc/include/ignite/odbc/config/connection_string_parser.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index eb0d1fede..41b115af0 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -183,7 +183,7 @@ namespace ignite */ struct BoolParseResult { - enum class Type + enum Type { AI_FALSE, From 9e639d1c4c5b4950d43b9e726cae454d826adc8d Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 27 Jan 2022 15:35:52 -0800 Subject: [PATCH 092/165] [AD-522] fix build errors after develop branch merge * update schema checkbox string * make edit row height single * update SetTcpPort to SetPort etc * define default value for sshEnable --- .../include/ignite/odbc/config/configuration.h | 2 +- .../win/src/system/ui/dsn_configuration_window.cpp | 14 ++++++-------- src/odbc/src/connection.cpp | 1 - 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/configuration.h b/src/odbc/include/ignite/odbc/config/configuration.h index 605820a8c..640e89388 100644 --- a/src/odbc/include/ignite/odbc/config/configuration.h +++ b/src/odbc/include/ignite/odbc/config/configuration.h @@ -775,7 +775,7 @@ namespace ignite SettableValue tlsCaFile = DefaultValue::tlsCaFile; /** The SSH enable option for the internal SSH tunnel. */ - SettableValue sshEnable; + SettableValue sshEnable = DefaultValue::sshEnable; /** The SSH host username for the internal SSH tunnel. */ SettableValue sshUser = DefaultValue::sshUser; diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index ec6086aa6..2f35dbdef 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -50,7 +50,6 @@ namespace ignite schemaLabel(), schemaEdit(), refreshSchemaCheckBox(), - // internal SSH tunnel vars sshEnableCheckBox(), sshUserLabel(), sshUserEdit(), @@ -63,7 +62,6 @@ namespace ignite sshStrictHostKeyCheckingCheckBox(), sshKnownHostsFileLabel(), sshKnownHostsFileEdit(), - // end of SSH vars appNameLabel(), appNameEdit(), readPreferenceLabel(), @@ -179,7 +177,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - std::string tmp = common::LexicalCast(config.GetTcpPort()); + std::string tmp = common::LexicalCast(config.GetPort()); val = tmp.c_str(); portLabel = CreateLabel( labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, @@ -263,9 +261,9 @@ namespace ignite val = config.GetSshPrivateKeyPassphrase().c_str(); // ssh private key passphrase label requires double the row height due to the long label. sshPrivateKeyPassphraseLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT * 2, - "SSH Private Key Passphrase:", ChildId::SSH_PRIVATE_KEY_PASSPHRASE_LABEL); + "SSH Private Key File Passphrase:", ChildId::SSH_PRIVATE_KEY_PASSPHRASE_LABEL); sshPrivateKeyPassphraseEdit = CreateEdit(editPosX, rowPos, editSizeX, - ROW_HEIGHT * 2, val, ChildId::SSH_PRIVATE_KEY_PASSPHRASE_EDIT); + ROW_HEIGHT, val, ChildId::SSH_PRIVATE_KEY_PASSPHRASE_EDIT); rowPos += INTERVAL + ROW_HEIGHT * 2; @@ -394,7 +392,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; refreshSchemaCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Refresh Schema", ChildId::REFRESH_SCHEMA_CHECK_BOX, config.IsRefreshSchema()); + "Refresh Schema (Caution: use only when necessary to update schema)", ChildId::REFRESH_SCHEMA_CHECK_BOX, config.IsRefreshSchema()); rowPos += INTERVAL + ROW_HEIGHT; @@ -693,7 +691,7 @@ namespace ignite int16_t port = common::LexicalCast< int16_t >(portStr); if (port <= 0) - port = config.GetTcpPort(); + port = config.GetPort(); LOG_MSG("Retrieving arguments:"); LOG_MSG("DSN: " << dsnStr); @@ -704,7 +702,7 @@ namespace ignite // username and password intentionally not logged for security reasons cfg.SetDsn(dsnStr); - cfg.SetTcpPort(port); + cfg.SetPort(port); cfg.SetHostname(hostnameStr); cfg.SetDatabase(databaseStr); cfg.SetUser(userStr); diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index 8586df08c..db1a0fec2 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -27,7 +27,6 @@ #include "ignite/odbc/log.h" #include "ignite/odbc/utility.h" #include "ignite/odbc/environment.h" -#include "ignite/odbc/end_point.h" #include "ignite/odbc/statement.h" #include "ignite/odbc/connection.h" #include "ignite/odbc/message.h" From d27b4918a3869b044d8881fe29c83ae3c516b21a Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 28 Jan 2022 11:50:15 -0800 Subject: [PATCH 093/165] [AD-522] enable encrypt password for ssh private key passphrase * modify refresh schema checkbox string to fit better * remove log message for ssh private key passphrase to increase security --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 2f35dbdef..69fa90482 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -263,7 +263,7 @@ namespace ignite sshPrivateKeyPassphraseLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT * 2, "SSH Private Key File Passphrase:", ChildId::SSH_PRIVATE_KEY_PASSPHRASE_LABEL); sshPrivateKeyPassphraseEdit = CreateEdit(editPosX, rowPos, editSizeX, - ROW_HEIGHT, val, ChildId::SSH_PRIVATE_KEY_PASSPHRASE_EDIT); + ROW_HEIGHT, val, ChildId::SSH_PRIVATE_KEY_PASSPHRASE_EDIT, ES_PASSWORD); rowPos += INTERVAL + ROW_HEIGHT * 2; @@ -392,7 +392,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; refreshSchemaCheckBox = CreateCheckBox(labelPosX, rowPos, checkBoxSize, ROW_HEIGHT, - "Refresh Schema (Caution: use only when necessary to update schema)", ChildId::REFRESH_SCHEMA_CHECK_BOX, config.IsRefreshSchema()); + "Refresh Schema (Caution: use temporarily to update schema)", ChildId::REFRESH_SCHEMA_CHECK_BOX, config.IsRefreshSchema()); rowPos += INTERVAL + ROW_HEIGHT; @@ -731,7 +731,6 @@ namespace ignite LOG_MSG("SSH user: " << sshUserStr); LOG_MSG("SSH host: " << sshHostStr); LOG_MSG("SSH private key file: " << sshPrivateKeyFileStr); - LOG_MSG("SSH private key passphrase: " << sshPrivateKeyPassphraseStr); LOG_MSG("SSH strict host key checking: " << (sshStrictHostKeyChecking ? "true" : "false")); LOG_MSG("SSH known hosts file: " << sshKnownHostsFileStr); From 107e016f9c17907682c2f2bc9d541fbee7c17fe1 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 28 Jan 2022 13:28:41 -0800 Subject: [PATCH 094/165] [AD-521] add comments and notes for starting AD-521 --- src/odbc/src/jni/java.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index dcd21b0b3..604527518 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -210,13 +210,22 @@ namespace ignite JniMethod( "getPropertiesFromConnectionString", "(Ljava/lang/String;)Lsoftware/amazon/documentdb/jdbc/DocumentDbConnectionProperties;", - true); + true); + + // todo code draft -AL-. After constants all defined, work on the JNI wrappers with Bruce + //const char* C_DOCUMENTDB_CONNECTION = + // "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; + //JniMethod M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING = + // JniMethod( + // "getPropertiesFromConnectionString", + // "(Ljava/lang/String;)Lsoftware/amazon/documentdb/jdbc/DocumentDbConnectionProperties;", + // true); const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; const char* C_DRIVERMANAGER = "java/sql/DriverManager"; JniMethod M_DRIVERMANAGER_GET_CONNECTION = - JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); + JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); // true/false defines whether it is true -> static/instance const char* C_JAVA_SQL_CONNECTION = "java/sql/Connection"; JniMethod M_JAVA_SQL_CONNECTION_CLOSE = JniMethod("close", "()V", false); From 48405a3d678d34f5866d710f8bb6efaea895f7d2 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 28 Jan 2022 14:26:17 -0800 Subject: [PATCH 095/165] [AD-509] update readMe to include directions about saving Java bin and server directories. * reason: ODBC JNI calls have a dependency on `jvm.dll`, as a result, the ODBC driver cannot operate properly unless the Java bin and server directories are included in the path. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cb1308e83..06f382dad 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,7 @@ 1. Ensure to add path to WiX executables (e.g. `C:\Program Files (x86)\WiX Toolset v3.11\bin`) 4. Java **JDK** (version 8+ - 17 recommended) 1. Ensure to set `JAVA_HOME`. + 2. Ensure to save Java `\bin` and `\server` directories to the User `PATH` variable. 5. Boost Test Framework 1. Install via [VCPKG](https://vcpkg.io/en/getting-started.html) using `.\vcpkg install openssl:x64-windows boost-test:x64-windows boost-asio:x64-windows boost-chrono:x64-windows boost-interprocess:x64-windows boost-regex:x64-windows boost-system:x64-windows boost-thread:x64-windows` 6. Run one of the build scripts to create an initial compilation. @@ -37,7 +38,8 @@ 4. `brew install boost` 5. Install Java **JDK** (version 8+ - 17 recommended) - This can be done through Homebrew using `brew install --cask temurin`. - - Ensure to set `JAVA_HOME`. + - Ensure to set `JAVA_HOME`. + - Ensure to save Java `/bin` and `/server` directories to the User `PATH` variable. 6. If creating a debug build (`./build_mac_debug64.sh`), LLVM is required. - If you only have XCode Command Line Tools, use the LLVM included with XCode by modifying the PATH with `export PATH=/Library/Developer/CommandLineTools/usr/bin/:$PATH`. Ensure this XCode path comes first in $PATH. If error occurs, check that clang and llvm are under folder Library/Developer/CommandLineTools/usr/bin. - If you have XCode application, to ensure LLVM and CMake are compatible, use the LLVM included with XCode by modifying the PATH with `export PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/:$PATH`. From a663492f9dd8c24834b7bf9da6a5efc867524340 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 28 Jan 2022 14:43:30 -0800 Subject: [PATCH 096/165] [AD-522] reduce space between ssh private key passphrase and the checkbox below --- src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 69fa90482..764e012c2 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -265,7 +265,7 @@ namespace ignite sshPrivateKeyPassphraseEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SSH_PRIVATE_KEY_PASSPHRASE_EDIT, ES_PASSWORD); - rowPos += INTERVAL + ROW_HEIGHT * 2; + rowPos += INTERVAL + ROW_HEIGHT; // SSH Strict Host Key Check check box needs to have editSizeX as size because the string is long sshStrictHostKeyCheckingCheckBox = CreateCheckBox( From 7ab94b9386955c615194c90254afc2028a62ccf8 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 31 Jan 2022 10:55:18 -0800 Subject: [PATCH 097/165] [AD-521] define constants for Java GetSshLocalPort method call --- src/odbc/include/ignite/odbc/jni/java.h | 1 + src/odbc/src/jni/java.cpp | 15 ++++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index 3925aaf0a..18d0142b2 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -246,6 +246,7 @@ namespace ignite { jmethodID m_DocumentDbConnectionPropertiesGetPropertiesFromConnectionString; jclass c_DocumentDbConnection; + jmethodID m_DocumentDbConnectionGetSshLocalPort; jmethodID m_DocumentDbConnectionInit; jmethodID m_DocumentDbClose; diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 604527518..3f53e9dd2 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -212,16 +212,12 @@ namespace ignite "(Ljava/lang/String;)Lsoftware/amazon/documentdb/jdbc/DocumentDbConnectionProperties;", true); - // todo code draft -AL-. After constants all defined, work on the JNI wrappers with Bruce - //const char* C_DOCUMENTDB_CONNECTION = - // "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; - //JniMethod M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING = - // JniMethod( - // "getPropertiesFromConnectionString", - // "(Ljava/lang/String;)Lsoftware/amazon/documentdb/jdbc/DocumentDbConnectionProperties;", - // true); + // todo code draft -AL-. After constants all defined (define constants here), work on the JNI wrappers with Bruce + const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnection"; + JniMethod M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT = + JniMethod("getSshLocalPort", "()I", false); - const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; + // const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; const char* C_DRIVERMANAGER = "java/sql/DriverManager"; JniMethod M_DRIVERMANAGER_GET_CONNECTION = @@ -437,6 +433,7 @@ namespace ignite c_DocumentDbConnection = FindClass(env, C_DOCUMENTDB_CONNECTION); //m_DocumentDbConnectionInit = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_PROPERTIES_INIT); + m_DocumentDbConnectionGetSshLocalPort = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT); c_DriverManager = FindClass(env, C_DRIVERMANAGER); m_DriverManagerGetConnection = FindMethod(env, c_DriverManager, M_DRIVERMANAGER_GET_CONNECTION); From d41e02713bca7a86f35ef999d72d54c1a282a985 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 31 Jan 2022 11:00:42 -0800 Subject: [PATCH 098/165] [AD-521] integrate code review feedback from Andie * refactors with comment changes and log changes --- .../os/win/src/system/ui/dsn_configuration_window.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 764e012c2..4092e36b4 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -34,7 +34,7 @@ namespace ignite namespace ui { DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, config::Configuration& config): - CustomWindow(parent, "IgniteConfigureDsn", "Configure Amazon DocumentDB DSN Latest"), + CustomWindow(parent, "IgniteConfigureDsn", "Configure Amazon DocumentDB DSN"), width(730), height(515), connectionSettingsGroupBox(), @@ -546,7 +546,7 @@ namespace ignite case ChildId::USER_EDIT: case ChildId::PASSWORD_EDIT: { - // if window has been created. Check + // Check if window has been created. if (created) { okButton->SetEnabled( nameEdit->HasText() @@ -752,8 +752,8 @@ namespace ignite tlsCaFileEdit->GetText(tlsCaStr); LOG_MSG("TLS/SSL Encryption: " << (tls ? "true" : "false")); - LOG_MSG("tls Allow Invalid Hostnames: " << (tlsAllowInvalidHostnames ? "true" : "false")); - LOG_MSG("TLS CA (Certificate Authority) File name: " << tlsCaStr); + LOG_MSG("TLS Allow Invalid Hostnames: " << (tlsAllowInvalidHostnames ? "true" : "false")); + LOG_MSG("TLS CA (Certificate Authority) File: " << tlsCaStr); cfg.SetTls(tls); cfg.SetTlsAllowInvalidHostnames(tlsAllowInvalidHostnames); From 6c16725b0d7c9e2f028cafc842499892e27239be Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 31 Jan 2022 13:37:43 -0800 Subject: [PATCH 099/165] [AD-521] refactor code * make open brace bracket start on new line for JVMException * remove excess space --- src/odbc/src/jni/java.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 3f53e9dd2..58ce058fc 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -115,7 +115,8 @@ namespace ignite } /* --- Startup exception. --- */ - class JvmException : public std::exception { + class JvmException : public std::exception + { // No-op. }; @@ -210,7 +211,7 @@ namespace ignite JniMethod( "getPropertiesFromConnectionString", "(Ljava/lang/String;)Lsoftware/amazon/documentdb/jdbc/DocumentDbConnectionProperties;", - true); + true); // todo code draft -AL-. After constants all defined (define constants here), work on the JNI wrappers with Bruce const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnection"; @@ -221,7 +222,7 @@ namespace ignite const char* C_DRIVERMANAGER = "java/sql/DriverManager"; JniMethod M_DRIVERMANAGER_GET_CONNECTION = - JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); // true/false defines whether it is true -> static/instance + JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); // -AL- true/false defines whether it is true -> static/instance const char* C_JAVA_SQL_CONNECTION = "java/sql/Connection"; JniMethod M_JAVA_SQL_CONNECTION_CLOSE = JniMethod("close", "()V", false); From 1db5b3fced43519bb091f5f080177268afda99d1 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 09:10:46 -0800 Subject: [PATCH 100/165] [AD-427] Tracer Code - Limited Capability to load metadata - work-in-progress. --- .../win/include/ignite/common/concurrent_os.h | 3 + src/odbc-test/CMakeLists.txt | 117 ++--- src/odbc-test/include/odbc_test_suite.h | 8 +- src/odbc-test/src/connection_test.cpp | 73 +-- src/odbc-test/src/java_test.cpp | 222 +++++++++ src/odbc-test/src/odbc_test_suite.cpp | 33 +- src/odbc/include/ignite/odbc/connection.h | 22 +- src/odbc/include/ignite/odbc/jni/java.h | 62 ++- src/odbc/include/ignite/odbc/log.h | 12 +- .../win/include/ignite/odbc/common/common.h | 6 +- src/odbc/src/app/application_data_buffer.cpp | 2 - src/odbc/src/connection.cpp | 91 +--- src/odbc/src/jni/java.cpp | 453 +++++++++++++++--- src/odbc/src/jni/os/linux/utils.cpp | 4 +- src/odbc/src/jni/os/win/utils.cpp | 12 +- 15 files changed, 811 insertions(+), 309 deletions(-) create mode 100644 src/odbc-test/src/java_test.cpp diff --git a/src/common/os/win/include/ignite/common/concurrent_os.h b/src/common/os/win/include/ignite/common/concurrent_os.h index b1e89164c..22bf36c34 100644 --- a/src/common/os/win/include/ignite/common/concurrent_os.h +++ b/src/common/os/win/include/ignite/common/concurrent_os.h @@ -32,6 +32,9 @@ namespace ignite { namespace concurrent { + // Forward declaration + class ConditionVariable; + /** * Static class to manage memory visibility semantics. */ diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 77294465b..44a469c8f 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -28,7 +28,7 @@ find_package(Boost 1.53 REQUIRED COMPONENTS unit_test_framework chrono thread sy find_package(ODBC REQUIRED) include_directories(SYSTEM ${ODBC_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${JNI_INCLUDE_DIRS}) -include_directories(include ../odbc/include ../network/include) +include_directories(include ../odbc/include) if (WIN32) include_directories(../odbc/os/win/include) else () @@ -39,68 +39,59 @@ endif() set(SOURCES src/connection_test.cpp src/dummy_test.cpp + src/java_test.cpp src/odbc_test_suite.cpp src/test_utils.cpp + ../odbc/src/app/application_data_buffer.cpp + ../odbc/src/app/parameter.cpp + ../odbc/src/app/parameter_set.cpp + ../odbc/src/column.cpp + ../odbc/src/common/big_integer.cpp + ../odbc/src/common/bits.cpp ../odbc/src/common/concurrent.cpp + ../odbc/src/common/decimal.cpp ../odbc/src/common/utils.cpp + ../odbc/src/common_types.cpp + ../odbc/src/config/configuration.cpp + ../odbc/src/config/config_tools.cpp + ../odbc/src/config/connection_info.cpp + ../odbc/src/config/connection_string_parser.cpp + ../odbc/src/connection.cpp + ../odbc/src/cursor.cpp + ../odbc/src/diagnostic/diagnosable_adapter.cpp + ../odbc/src/diagnostic/diagnostic_record_storage.cpp + ../odbc/src/diagnostic/diagnostic_record.cpp + ../odbc/src/dsn_config.cpp + ../odbc/src/environment.cpp + ../odbc/src/ignite_error.cpp ../odbc/src/jni/java.cpp -# TODO uncomment/rework the tests after get some connectivity and functionalities working. -# src/teamcity/teamcity_boost.cpp -# src/teamcity/teamcity_messages.cpp -# src/parser_test.cpp -# src/cursor_test.cpp -# src/connection_info_test.cpp -# src/application_data_buffer_test.cpp -# src/column_test.cpp -# src/configuration_test.cpp -# src/row_test.cpp -# src/meta_queries_test.cpp -# src/utility_test.cpp -# src/queries_test.cpp -# src/queries_ssl_test.cpp -# src/sql_test_suite_fixture.cpp -# src/sql_string_functions_test.cpp -# src/sql_numeric_functions_test.cpp -# src/sql_aggregate_functions_test.cpp -# src/sql_system_functions_test.cpp -# src/sql_esc_convert_function_test.cpp -# src/sql_operators_test.cpp -# src/sql_value_expressions_test.cpp -# src/sql_types_test.cpp -# src/sql_date_time_functions_test.cpp -# src/sql_outer_join_test.cpp -# src/sql_get_info_test.cpp -# src/api_robustness_test.cpp -# src/attributes_test.cpp -# src/errors_test.cpp -# src/types_test.cpp -# src/transaction_test.cpp -# src/authentication_test.cpp -# src/sql_parsing_test.cpp -# src/streaming_test.cpp -# src/cursor_binding_test.cpp -# src/test_server.cpp -# ../odbc/src/log.cpp -# ../odbc/src/cursor.cpp -# ../odbc/src/diagnostic/diagnostic_record.cpp -# ../odbc/src/diagnostic/diagnostic_record_storage.cpp -# ../odbc/src/config/config_tools.cpp -# ../odbc/src/config/configuration.cpp -# ../odbc/src/config/connection_info.cpp -# ../odbc/src/config/connection_string_parser.cpp -# ../odbc/src/app/application_data_buffer.cpp -# ../odbc/src/ssl_mode.cpp -# ../odbc/src/sql/sql_parser.cpp -# ../odbc/src/sql/sql_lexer.cpp -# ../odbc/src/sql/sql_set_streaming_command.cpp -# ../odbc/src/sql/sql_utils.cpp -# ../odbc/src/row.cpp -# ../odbc/src/protocol_version.cpp -# ../odbc/src/column.cpp -# ../odbc/src/common_types.cpp -# ../odbc/src/utility.cpp -# ../odbc/src/result_page.cpp -# ../odbc/src/nested_tx_mode.cpp + ../odbc/src/log.cpp + ../odbc/src/message.cpp + ../odbc/src/meta/column_meta.cpp + ../odbc/src/meta/table_meta.cpp + ../odbc/src/nested_tx_mode.cpp + ../odbc/src/protocol_version.cpp + ../odbc/src/query/batch_query.cpp + ../odbc/src/query/column_metadata_query.cpp + ../odbc/src/query/data_query.cpp + ../odbc/src/query/foreign_keys_query.cpp + ../odbc/src/query/primary_keys_query.cpp + ../odbc/src/query/special_columns_query.cpp + ../odbc/src/query/streaming_query.cpp + ../odbc/src/query/type_info_query.cpp + ../odbc/src/query/table_metadata_query.cpp + ../odbc/src/sql/sql_lexer.cpp + ../odbc/src/sql/sql_parser.cpp + ../odbc/src/sql/sql_set_streaming_command.cpp + ../odbc/src/sql/sql_utils.cpp + ../odbc/src/result_page.cpp + ../odbc/src/row.cpp + ../odbc/src/ssl_mode.cpp + ../odbc/src/statement.cpp + ../odbc/src/streaming/streaming_batch.cpp + ../odbc/src/streaming/streaming_context.cpp + ../odbc/src/type_traits.cpp + ../odbc/src/utility.cpp ) if (WIN32) @@ -108,6 +99,10 @@ if (WIN32) ../odbc/os/win/src/common/concurrent_os.cpp ../odbc/os/win/src/common/platform_utils.cpp ../odbc/src/jni/os/win/utils.cpp + ../odbc/os/win/src/system_dsn.cpp + ../odbc/os/win/src/system/ui/custom_window.cpp + ../odbc/os/win/src/system/ui/dsn_configuration_window.cpp + ../odbc/os/win/src/system/ui/window.cpp ) else() # TODO: Ensure MacOS is portable. https://bitquill.atlassian.net/browse/AD-525 @@ -120,11 +115,17 @@ endif() add_executable(${TARGET} ${SOURCES}) +target_link_libraries(${TARGET} ${ODBC_LIBRARIES}) target_link_libraries(${TARGET} ${Boost_LIBRARIES} ignite ${ODBC_LIBRARY}) target_code_coverage(${TARGET} PUBLIC AUTO ALL) if (WIN32) remove_definitions(-DUNICODE=1) + add_definitions(-DTARGET_MODULE_FULL_NAME="$") + if (MSVC_VERSION GREATER_EQUAL 1900) + target_link_libraries(${TARGET} legacy_stdio_definitions odbccp32 shlwapi) + endif() + else() add_definitions(-DBOOST_TEST_DYN_LINK) endif() diff --git a/src/odbc-test/include/odbc_test_suite.h b/src/odbc-test/include/odbc_test_suite.h index 6bd00a63a..414daabf6 100644 --- a/src/odbc-test/include/odbc_test_suite.h +++ b/src/odbc-test/include/odbc_test_suite.h @@ -37,8 +37,6 @@ #include -#include "ignite/ignite.h" - namespace ignite { namespace odbc @@ -352,6 +350,12 @@ namespace ignite */ SQLRETURN PrepareQuery(const std::string& qry); + /** + * Creates the standard DSN connection string. + */ + void CreateDsnConnectionString(std::string& connectionString, + const std::string& username = std::string()) const; + /** ODBC Environment. */ SQLHENV env; diff --git a/src/odbc-test/src/connection_test.cpp b/src/odbc-test/src/connection_test.cpp index 28714a040..d28a85643 100644 --- a/src/odbc-test/src/connection_test.cpp +++ b/src/odbc-test/src/connection_test.cpp @@ -16,7 +16,7 @@ */ #ifdef _WIN32 -# include +# include #endif #include @@ -39,14 +39,7 @@ using namespace boost::unit_test; */ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite { - /** - * Constructor. - */ - ConnectionTestSuiteFixture() : - OdbcTestSuite() - { - // No-op. - } + using odbc::OdbcTestSuite::OdbcTestSuite; /** * Execute the query and return an error code. @@ -83,32 +76,10 @@ struct ConnectionTestSuiteFixture: odbc::OdbcTestSuite return code; } - static void SetConnectionString(std::string& connectionString, - const std::string& username = std::string()) { - // NOTE: Assuming we are using internal SSH tunnel - std::string user = common::GetEnv("DOC_DB_USER_NAME", "documentdb"); - std::string password = common::GetEnv("DOC_DB_PASSWORD", ""); - std::string host = common::GetEnv("DOC_DB_HOST", ""); - std::string port = "27017"; - if (!username.empty()) { - user = username; - } - - connectionString = - "DRIVER={Apache Ignite};" - "ADDRESS=" + host + ":" + port + ";" - "SCHEMA=test;" - "USER=" + user + ";" - "PASSWORD=" + password + ";"; - } - /** * Destructor. */ - ~ConnectionTestSuiteFixture() - { - // No-op. - } + ~ConnectionTestSuiteFixture() override = default; }; @@ -117,54 +88,20 @@ BOOST_FIXTURE_TEST_SUITE(ConnectionTestSuite, ConnectionTestSuiteFixture) BOOST_AUTO_TEST_CASE(TestConnectionRestore) { std::string connectionString; - SetConnectionString(connectionString); - - Connect(connectionString); - Disconnect(); - - // TODO: [AD-507] Re-enable when querying is supported. - // https://bitquill.atlassian.net/browse/AD-507 - - //// Check that query was successfully executed. - //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); - - //// Query execution should throw ODBC error. - //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08S01"); - - //// Reusing a closed connection should not crash an application. - //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), "08001"); - - //// Check that connection was restored. - //BOOST_CHECK_EQUAL(ExecQueryAndReturnError(), ""); - -} - -BOOST_AUTO_TEST_CASE(TestConnectionMemoryLeak) -{ - std::string connectionString; - SetConnectionString(connectionString); + CreateDsnConnectionString(connectionString); Connect(connectionString); - - // TODO: [AD-507] Re-enable when querying is supported. - // https://bitquill.atlassian.net/browse/AD-507 - // ExecQuery("Select * from Test"); - Disconnect(); } BOOST_AUTO_TEST_CASE(TestConnectionInvalidUser) { std::string connectionString; - SetConnectionString(connectionString, "invaliduser"); + CreateDsnConnectionString(connectionString, "invaliduser"); ExpectConnectionReject(connectionString, "08001: Failed to establish connection with the host.\n" "Invalid username or password or user is not authorized on database 'test'. " "Please check your settings. Authorization failed for user 'invaliduser' on database 'admin' with mechanism"); - // TODO: [AD-507] Re-enable when querying is supported. - // https://bitquill.atlassian.net/browse/AD-507 - // ExecQuery("Select * from Test"); - Disconnect(); } diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp new file mode 100644 index 000000000..36ffacdcd --- /dev/null +++ b/src/odbc-test/src/java_test.cpp @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef _WIN32 +# include +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_utils.h" +#include "odbc_test_suite.h" + +using namespace ignite; +using namespace ignite_test; +using namespace boost::unit_test; +using namespace odbc; +using namespace odbc::config; +using namespace odbc::jni; +using namespace odbc::jni::java; +using namespace odbc::common::concurrent; + +/** + * Test setup fixture. + */ +struct JavaTestSuiteFixture: odbc::OdbcTestSuite +{ + using odbc::OdbcTestSuite::OdbcTestSuite; + + /** + * Execute the query and return an error code. + */ + std::string ExecQueryAndReturnError() + { + SQLCHAR selectReq[] = "select count(*) from TestType"; + + SQLRETURN ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq)); + + std::string err; + + if (!SQL_SUCCEEDED(ret)) + err = ExtractErrorCode(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + return err; + } + + /** + * Extract code from ODBC error message. + * + * @param err Error message. + * @return Error code. + */ + static std::string ExtractErrorCode(const std::string& err) + { + std::string code; + + size_t idx = err.find(':'); + + if ((idx != std::string::npos) && (idx > 0)) + code = err.substr(0, idx); + + return code; + } + + SharedPointer< JniContext > GetJniContext(std::vector< char* >& opts) const { + + SharedPointer< JniContext > ctx(JniContext::Create( + &opts[0], static_cast< int >(opts.size()), JniHandlers())); + BOOST_CHECK(ctx.Get()); + return ctx; + } + + std::string GetJdbcConnectionString() const { + std::string dsnConnectionString; + CreateDsnConnectionString(dsnConnectionString); + + Configuration config; + ConnectionStringParser parser(config); + parser.ParseConnectionString(dsnConnectionString, nullptr); + std::string jdbcConnectionString = + Connection::FormatJdbcConnectionString(config); + return jdbcConnectionString; + } + + void PrepareContext() { + if (!_prepared) { + _jdbcConnectionString = GetJdbcConnectionString(); + std::string cp = ResolveDocumentDbHome(); + BuildJvmOptions(cp, _opts); + _ctx = GetJniContext(_opts); + _prepared = true; + } + } + + void CleanUpContext() { + using namespace odbc::common; + std::for_each(_opts.begin(), _opts.end(), ReleaseChars); + _opts.clear(); + _ctx = nullptr; + _prepared = false; + } + + /** + * Destructor. + */ + ~JavaTestSuiteFixture() override { + CleanUpContext(); + } + + bool _prepared = false; + + std::string _jdbcConnectionString; + + std::vector< char* > _opts; + + SharedPointer< JniContext > _ctx; +}; + + +BOOST_FIXTURE_TEST_SUITE(JavaTestSuite, JavaTestSuiteFixture) + +BOOST_AUTO_TEST_CASE(TestDriverManagerGetConnection) +{ + PrepareContext(); + + JniErrorInfo errInfo; + SharedPointer< GlobalJObject > connection; + bool success = _ctx.Get()->DriverManagerGetConnection(_jdbcConnectionString.c_str(), connection, &errInfo); + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(connection.Get()); + + _ctx.Get()->ConnectionClose(connection, &errInfo); + connection = SharedPointer< GlobalJObject >(nullptr); +} + +BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { + PrepareContext(); + + JniErrorInfo errInfo; + SharedPointer< GlobalJObject > connection; + bool success = _ctx.Get()->DriverManagerGetConnection( + _jdbcConnectionString.c_str(), connection, &errInfo); + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(connection.Get()); + + SharedPointer< GlobalJObject > databaseMetaData; + if (!_ctx.Get()->ConnectionGetMetaData(connection, databaseMetaData, + &errInfo)) { + std::string errMsg = errInfo.errMsg; + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(databaseMetaData.Get()); + + _ctx.Get()->ConnectionClose(connection, &errInfo); + connection = nullptr; +} + +BOOST_AUTO_TEST_CASE(TestDatabaseMetaDataGetTables) { + PrepareContext(); + + JniErrorInfo errInfo; + SharedPointer< GlobalJObject > connection; + bool success = _ctx.Get()->DriverManagerGetConnection( + _jdbcConnectionString.c_str(), connection, &errInfo); + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(connection.Get()); + + SharedPointer< GlobalJObject > databaseMetaData; + if (!_ctx.Get()->ConnectionGetMetaData(connection, databaseMetaData, &errInfo)) { + std::string errMsg = errInfo.errMsg; + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(databaseMetaData.Get()); + + SharedPointer< GlobalJObject > resultSet; + if (!_ctx.Get()->DatabaseMetaDataGetTables(databaseMetaData, resultSet, + &errInfo)) { + std::string errMsg = errInfo.errMsg; + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(resultSet.Get()); + + _ctx.Get()->ConnectionClose(connection, &errInfo); + connection = nullptr; +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/odbc-test/src/odbc_test_suite.cpp b/src/odbc-test/src/odbc_test_suite.cpp index 1b2ece743..41fcd3b49 100644 --- a/src/odbc-test/src/odbc_test_suite.cpp +++ b/src/odbc-test/src/odbc_test_suite.cpp @@ -132,7 +132,7 @@ namespace ignite { // Releasing statement handle. SQLFreeHandle(SQL_HANDLE_STMT, stmt); - stmt = NULL; + stmt = nullptr; } if (dbc) @@ -142,7 +142,7 @@ namespace ignite // Releasing allocated handles. SQLFreeHandle(SQL_HANDLE_DBC, dbc); - dbc = NULL; + dbc = nullptr; } } @@ -221,7 +221,7 @@ namespace ignite float OdbcTestSuite::GetTestFloatField(int64_t idx) { - return static_cast(idx * 0.5f); + return static_cast(idx) * 0.5f; } void OdbcTestSuite::CheckTestFloatValue(int idx, float value) @@ -232,7 +232,7 @@ namespace ignite double OdbcTestSuite::GetTestDoubleField(int64_t idx) { - return static_cast(idx * 0.25f); + return static_cast(idx) * 0.25f; } void OdbcTestSuite::CheckTestDoubleValue(int idx, double value) @@ -243,7 +243,7 @@ namespace ignite bool OdbcTestSuite::GetTestBoolField(int64_t idx) { - return static_cast(idx % 2 == 0); + return ((idx % 2) == 0); } void OdbcTestSuite::CheckTestBoolValue(int idx, bool value) @@ -420,7 +420,7 @@ namespace ignite // Inserting values. for (SQLSMALLINT i = 0; i < recordsNum; ++i) { - key = i + 1; + key = static_cast(i) + 1; std::string val = GetTestString(i); CopyStringToBuffer(strField, val, sizeof(strField)); @@ -787,5 +787,26 @@ namespace ignite BOOST_CHECK_EQUAL(recordsNum, selectedRecordsNum); } + + void OdbcTestSuite::CreateDsnConnectionString(std::string& connectionString, + const std::string& username) const { + // NOTE: Assuming we are using internal SSH tunnel + std::string user = common::GetEnv("DOC_DB_USER_NAME", "documentdb"); + std::string password = common::GetEnv("DOC_DB_PASSWORD", ""); + std::string host = common::GetEnv("DOC_DB_HOST", ""); + std::string port = "27017"; + if (!username.empty()) { + user = username; + } + + connectionString = + "DRIVER={Apache Ignite};" + "ADDRESS=" + host + ":" + port + ";" + "SCHEMA=test;" + "USER=" + user + ";" + "PASSWORD=" + password + ";"; + } + + } } diff --git a/src/odbc/include/ignite/odbc/connection.h b/src/odbc/include/ignite/odbc/connection.h index 0a917a50d..cf1616945 100644 --- a/src/odbc/include/ignite/odbc/connection.h +++ b/src/odbc/include/ignite/odbc/connection.h @@ -22,8 +22,6 @@ #include -#include - #include "ignite/odbc/parser.h" #include "ignite/odbc/config/connection_info.h" #include "ignite/odbc/config/configuration.h" @@ -31,6 +29,9 @@ #include "ignite/odbc/streaming/streaming_context.h" #include "ignite/odbc/odbc_error.h" #include "ignite/odbc/jni/java.h" +#include + +using ignite::odbc::jni::java::GlobalJObject; namespace ignite { @@ -312,7 +313,14 @@ namespace ignite */ void SetAttribute(int attr, void* value, SQLINTEGER valueLen); - private: + /** + * Formats the JDBC connection string from configuration values. + * @return the JDBC connection string. + */ + static std::string FormatJdbcConnectionString( + const config::Configuration& config); + + private: IGNITE_NO_COPY_ASSIGNMENT(Connection); /** @@ -489,12 +497,6 @@ namespace ignite */ bool TryRestoreConnection(IgniteError& err); - /** - * Formats the JDBC connection string from configuration values. - * @return the JDBC connection string. - */ - std::string FormatJdbcConnectionString() const; - /** * Creates JVM options */ @@ -548,7 +550,7 @@ namespace ignite config::ConnectionInfo info; /** Java connection object */ - jobject connection; + SharedPointer< GlobalJObject > connection; /** JVM options */ std::vector< char* > opts; diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index 3925aaf0a..d85921ca0 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -19,10 +19,14 @@ #define _IGNITE_ODBC_JNI_JAVA #include +#include #include #include +#include + +using ignite::odbc::common::concurrent::SharedPointer; namespace ignite { namespace odbc { @@ -191,6 +195,12 @@ namespace ignite { */ bool IGNITE_IMPORT_EXPORT IsJava9OrLater(); + /** + * Builds the JVM options + */ + void BuildJvmOptions(const std::string& cp, + std::vector< char* >& opts, int xms = 256, + int xmx = 1024); /** * JNI handlers holder. */ @@ -252,8 +262,20 @@ namespace ignite { jclass c_DriverManager; jmethodID m_DriverManagerGetConnection; - jclass c_JavaSqlConnection; - jmethodID m_JavaSqlConnectionClose; + jclass c_Connection; + jmethodID m_ConnectionClose; + jmethodID m_ConnectionGetMetaData; + + jclass c_ResultSet; + jmethodID m_ResultSetNext; + jmethodID m_ResultSetGetStringByIndex; + jmethodID m_ResultSetGetIntegerByIndex; + jmethodID m_ResultSetGetStringByName; + jmethodID m_ResultSetGetIntegerByName; + jmethodID m_ResultSetWasNull; + + jclass c_DatabaseMetaData; + jmethodID m_DatabaseMetaDataGetTables; jclass c_IgniteException; @@ -290,6 +312,27 @@ namespace ignite { void Destroy(JNIEnv* env); }; + /** + * Guard to ensure global reference cleanup. + */ + class GlobalJObject { + public: + GlobalJObject(JNIEnv* e, jobject obj); + + ~GlobalJObject(); + + jobject GetRef() const; + + private: + /** Environment. */ + JNIEnv* env; + + /** Target reference. */ + jobject ref; + + IGNITE_NO_COPY_ASSIGNMENT(GlobalJObject); + }; + /** * JNI JVM wrapper. */ @@ -398,10 +441,19 @@ namespace ignite { static void SetConsoleHandler(ConsoleWriteHandler consoleHandler); static int RemoveConsoleHandler(ConsoleWriteHandler consoleHandler); - jobject DocumentDbConnect(const char* connectionString, - JniErrorInfo* errInfo); + bool DriverManagerGetConnection(const char* connectionString, SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo); + void ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo); + bool ConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject>& databaseMetaData, JniErrorInfo* errInfo); + + bool DatabaseMetaDataGetTables(const SharedPointer< GlobalJObject >& databaseMetaData, SharedPointer< GlobalJObject >& resultSet, JniErrorInfo* errInfo); - void DocumentDbDisconnect(const jobject connection, JniErrorInfo* errInfo); + bool ResultSetNext(const SharedPointer< GlobalJObject >& resultSet, bool& hasNext, + JniErrorInfo* errInfo); + bool ResultSetGetString(const jobject resultSet, int columnIndex, std::string& value, bool& wasNull, JniErrorInfo* errInfo); + bool ResultSetGetString(const jobject resultSet, const std::string& columnName, std::string& value, bool& wasNull, JniErrorInfo* errInfo); + bool ResultSetGetInteger(const jobject resultSet, int columnIndex, int& value, bool& wasNull, JniErrorInfo* errInfo); + bool ResultSetGetInteger(const jobject resultSet, const std::string& columnName, int& value, bool& wasNull, JniErrorInfo* errInfo); + bool ResultSetWasNull(const jobject resultSet, bool& value, JniErrorInfo* errInfo); int64_t TargetInLongOutLong(jobject obj, int type, int64_t memPtr, JniErrorInfo* errInfo = NULL); diff --git a/src/odbc/include/ignite/odbc/log.h b/src/odbc/include/ignite/odbc/log.h index 2e361ea20..045c01796 100644 --- a/src/odbc/include/ignite/odbc/log.h +++ b/src/odbc/include/ignite/odbc/log.h @@ -25,12 +25,12 @@ #include "ignite/odbc/common/common.h" #include "ignite/odbc/common/concurrent.h" -# define LOG_MSG(param) \ - if (ignite::odbc::Logger* p = ignite::odbc::Logger::Get()) \ - { \ - ignite::odbc::LogStream lstream(p); \ - lstream << __FUNCTION__ << ": " << param; \ - } +#define LOG_MSG(param) \ + if (ignite::odbc::Logger* p = ignite::odbc::Logger::Get()) { \ + ignite::odbc::LogStream lstream(p); \ + lstream << __FUNCTION__ << ": " << param; \ + } \ + static_assert(true, "") \ namespace ignite { diff --git a/src/odbc/os/win/include/ignite/odbc/common/common.h b/src/odbc/os/win/include/ignite/odbc/common/common.h index e7cda4b52..3ef9574e3 100644 --- a/src/odbc/os/win/include/ignite/odbc/common/common.h +++ b/src/odbc/os/win/include/ignite/odbc/common/common.h @@ -14,8 +14,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef _IGNITE_COMMON_COMMON -#define _IGNITE_COMMON_COMMON +#ifndef _IGNITE_ODBC_COMMON_COMMON +#define _IGNITE_ODBC_COMMON_COMMON #define IGNITE_EXPORT __declspec(dllexport) #define IGNITE_IMPORT __declspec(dllimport) @@ -43,4 +43,4 @@ #define IGNITE_UNUSED(x) ((void) x) -#endif //_IGNITE_COMMON_COMMON \ No newline at end of file +#endif //_IGNITE_ODBC_COMMON_COMMON \ No newline at end of file diff --git a/src/odbc/src/app/application_data_buffer.cpp b/src/odbc/src/app/application_data_buffer.cpp index f4977bb09..0a05506e2 100644 --- a/src/odbc/src/app/application_data_buffer.cpp +++ b/src/odbc/src/app/application_data_buffer.cpp @@ -21,8 +21,6 @@ #include "ignite/odbc/common/bits.h" -#include "ignite/impl/binary/binary_utils.h" - #include "ignite/odbc/system/odbc_constants.h" #include "ignite/odbc/app/application_data_buffer.h" #include "ignite/odbc/utility.h" diff --git a/src/odbc/src/connection.cpp b/src/odbc/src/connection.cpp index d416b52d7..c737246fc 100644 --- a/src/odbc/src/connection.cpp +++ b/src/odbc/src/connection.cpp @@ -22,7 +22,6 @@ #include #include -#include #include "ignite/odbc/log.h" #include "ignite/odbc/utility.h" @@ -40,6 +39,10 @@ #include "ignite/odbc/common/concurrent.h" #include "ignite/odbc/common/utils.h" +using namespace ignite::odbc::jni::java; +using namespace ignite::odbc::common; +using namespace ignite::odbc::common::concurrent; + // Uncomment for per-byte debug. //#define PER_BYTE_DEBUG @@ -152,7 +155,7 @@ namespace ignite config = cfg; - if (connection) { + if (connection.Get()) { AddStatusRecord(SqlState::S08002_ALREADY_CONNECTED, "Already connected."); @@ -196,7 +199,7 @@ namespace ignite SqlResult::Type Connection::InternalRelease() { - if (!connection) + if (!connection.Get()) { AddStatusRecord(SqlState::S08003_NOT_CONNECTED, "Connection is not open."); @@ -212,13 +215,10 @@ namespace ignite void Connection::Close() { - if (connection) { - using namespace jni::java; - using namespace common::concurrent; + if (connection.Get()) { SharedPointer< JniContext > ctx(JniContext::Create(&opts[0], static_cast(opts.size()), JniHandlers())); JniErrorInfo errInfo; - // NOTE: DocumentDbDisconnect will notify JNI connection is no longer used - must set to nullptr. - ctx.Get()->DocumentDbDisconnect(connection, &errInfo); + ctx.Get()->ConnectionClose(connection, &errInfo); if (errInfo.code != java::IGNITE_JNI_ERR_SUCCESS) { // TODO: Determine if we need to error check the close. } @@ -398,7 +398,7 @@ namespace ignite { SQLUINTEGER *val = reinterpret_cast(buf); - *val = connection ? SQL_CD_FALSE : SQL_CD_TRUE; + *val = connection.Get() ? SQL_CD_FALSE : SQL_CD_TRUE; if (valueLen) *valueLen = SQL_IS_INTEGER; @@ -595,7 +595,7 @@ namespace ignite void Connection::EnsureConnected() { - if (connection) + if (connection.Get()) return; odbc::IgniteError err; @@ -610,25 +610,18 @@ namespace ignite { bool connected = false; - using namespace jni::java; - using namespace common::concurrent; - - if (connection) { + if (connection.Get()) { return true; } - std::string connectionString = FormatJdbcConnectionString(); + std::string connectionString = FormatJdbcConnectionString(config); JniErrorInfo errInfo; - std::string docdb_home = common::GetEnv("DOCUMENTDB_HOME") - + "\\documentdb-jdbc-1.1.0-all.jar"; - // 2. Resolve DOCUMENTDB_HOME. std::string home = jni::ResolveDocumentDbHome(); // 3. Create classpath. std::string cp = jni::CreateDocumentDbClasspath(std::string(), home); - if (cp.empty()) { err = odbc::IgniteError(odbc::IgniteError::IGNITE_ERR_JVM_NO_CLASSPATH, @@ -641,10 +634,16 @@ namespace ignite SetJvmOptions(cp); SharedPointer< JniContext > ctx(JniContext::Create(&opts[0], static_cast(opts.size()), JniHandlers(), &errInfo)); + if (errInfo.code != java::IGNITE_JNI_ERR_SUCCESS) { + IgniteError::SetError(errInfo.code, errInfo.errCls, errInfo.errMsg, err); + return false; + } if (ctx.Get()) { - jobject result = ctx.Get()->DocumentDbConnect( - connectionString.c_str(), &errInfo); - connected = (result && errInfo.code == java::IGNITE_JNI_ERR_SUCCESS); + SharedPointer< GlobalJObject > result; + bool success = ctx.Get()->DriverManagerGetConnection( + connectionString.c_str(), result, &errInfo); + connected = (success && result.Get() + && errInfo.code == java::IGNITE_JNI_ERR_SUCCESS); if (!connected) { err = odbc::IgniteError( odbc::IgniteError::IGNITE_ERR_SECURE_CONNECTION_FAILURE, @@ -660,7 +659,8 @@ namespace ignite return connected; } - std::string Connection::FormatJdbcConnectionString() const { + std::string Connection::FormatJdbcConnectionString( + const config::Configuration& config) { std::string host = "localhost"; std::string port = "27017"; if (!config.GetAddresses().empty()) { @@ -711,57 +711,14 @@ namespace ignite * @param cp Classpath. */ void Connection::SetJvmOptions(const std::string& cp) { - using namespace common; Deinit(); - - const size_t REQ_OPTS_CNT = 4; - const size_t JAVA9_OPTS_CNT = 6; - - opts.reserve(REQ_OPTS_CNT + JAVA9_OPTS_CNT); - - // 1. Set classpath. - std::string cpFull = "-Djava.class.path=" + cp; - - opts.push_back(CopyChars(cpFull.c_str())); - - // 3. Set Xms, Xmx. - std::string xmsStr = "-Xms" + std::to_string(256) + "m"; - std::string xmxStr = "-Xmx" + std::to_string(1024) + "m"; - - opts.push_back(CopyChars(xmsStr.c_str())); - opts.push_back(CopyChars(xmxStr.c_str())); - - // 4. Optional debug arguments - //std::string debugStr = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"; - //opts.push_back(CopyChars(debugStr.c_str())); - - // 5. Set file.encoding. - std::string fileEncParam = "-Dfile.encoding="; - std::string fileEncFull = fileEncParam + "UTF-8"; - opts.push_back(CopyChars(fileEncFull.c_str())); - - // Adding options for Java 9 or later - if (jni::java::IsJava9OrLater()) { - opts.push_back(CopyChars( - "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-exports=java.management/com.sun.jmx.mbeanserver=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-exports=jdk.internal.jvmstat/sun.jvmstat.monitor=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-exports=java.base/sun.reflect.generics.reflectiveObjects=ALL-UNNAMED")); - opts.push_back(CopyChars( - "--add-opens=jdk.management/com.sun.management.internal=ALL-UNNAMED")); - } + BuildJvmOptions(cp, opts); } /** * Deallocates all allocated data. */ void Connection::Deinit() { - using namespace common; std::for_each(opts.begin(), opts.end(), ReleaseChars); opts.clear(); } diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index dcd21b0b3..573c499be 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -23,11 +23,13 @@ #include #include +#include #include +#include #include #include -#include -#include + +using namespace ignite::odbc::common::concurrent; #ifndef JNI_VERSION_9 #define JNI_VERSION_9 0x00090000 @@ -114,6 +116,61 @@ namespace ignite return JNI_GetDefaultJavaVMInitArgs(&args) == JNI_OK; } + void BuildJvmOptions( + const std::string& cp, std::vector< char* >& opts, + int xms, int xmx) { + using namespace common; + + const size_t REQ_OPTS_CNT = 4; + const size_t JAVA9_OPTS_CNT = 6; + + opts.reserve(REQ_OPTS_CNT + JAVA9_OPTS_CNT); + + // 1. Set classpath. + std::string cpFull = "-Djava.class.path=" + cp; + + opts.push_back(CopyChars(cpFull.c_str())); + + // 3. Set Xms, Xmx. + std::string xmsStr = "-Xms" + std::to_string(xms) + "m"; + std::string xmxStr = "-Xmx" + std::to_string(xmx) + "m"; + + opts.push_back(CopyChars(xmsStr.c_str())); + opts.push_back(CopyChars(xmxStr.c_str())); + + // 4. Optional debug arguments + // std::string debugStr = + // "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"; + // opts.push_back(CopyChars(debugStr.c_str())); + + // 5. Set file.encoding. + std::string fileEncParam = "-Dfile.encoding="; + std::string fileEncFull = fileEncParam + "UTF-8"; + opts.push_back(CopyChars(fileEncFull.c_str())); + + // Adding options for Java 9 or later + if (jni::java::IsJava9OrLater()) { + opts.push_back( + CopyChars("--add-exports=java.base/" + "jdk.internal.misc=ALL-UNNAMED")); + opts.push_back(CopyChars( + "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED")); + opts.push_back( + CopyChars("--add-exports=java.management/" + "com.sun.jmx.mbeanserver=ALL-UNNAMED")); + opts.push_back( + CopyChars("--add-exports=jdk.internal.jvmstat/" + "sun.jvmstat.monitor=ALL-UNNAMED")); + opts.push_back( + CopyChars("--add-exports=java.base/" + "sun.reflect.generics.reflectiveObjects=" + "ALL-UNNAMED")); + opts.push_back(CopyChars( + "--add-opens=jdk.management/" + "com.sun.management.internal=ALL-UNNAMED")); + } + } + /* --- Startup exception. --- */ class JvmException : public std::exception { // No-op. @@ -171,55 +228,62 @@ namespace ignite delete[] errMsg; } - /** - * Guard to ensure global reference cleanup. - */ - class JniGlobalRefGuard - { - public: - JniGlobalRefGuard(JNIEnv *e, jobject obj) : env(e), ref(obj) - { - // No-op. - } - - ~JniGlobalRefGuard() - { - env->DeleteGlobalRef(ref); - } - - private: - /** Environment. */ - JNIEnv* env; - - /** Target reference. */ - jobject ref; + // Classes and method definitions. + const char* const C_THROWABLE = "java/lang/Throwable"; + JniMethod const M_THROWABLE_GET_MESSAGE = JniMethod("getMessage", "()Ljava/lang/String;", false); + JniMethod const M_THROWABLE_PRINT_STACK_TRACE = JniMethod("printStackTrace", "()V", false); - IGNITE_NO_COPY_ASSIGNMENT(JniGlobalRefGuard); - }; + const char* const C_CLASS = "java/lang/Class"; + JniMethod const M_CLASS_GET_NAME = JniMethod("getName", "()Ljava/lang/String;", false); - const char* C_THROWABLE = "java/lang/Throwable"; - JniMethod M_THROWABLE_GET_MESSAGE = JniMethod("getMessage", "()Ljava/lang/String;", false); - JniMethod M_THROWABLE_PRINT_STACK_TRACE = JniMethod("printStackTrace", "()V", false); - - const char* C_CLASS = "java/lang/Class"; - JniMethod M_CLASS_GET_NAME = JniMethod("getName", "()Ljava/lang/String;", false); - - const char* C_DOCUMENTDB_CONNECTION_PROPERTIES = + const char* const C_DOCUMENTDB_CONNECTION_PROPERTIES = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; - JniMethod M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING = + JniMethod const M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING = JniMethod( "getPropertiesFromConnectionString", "(Ljava/lang/String;)Lsoftware/amazon/documentdb/jdbc/DocumentDbConnectionProperties;", true); - const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; - - const char* C_DRIVERMANAGER = "java/sql/DriverManager"; - JniMethod M_DRIVERMANAGER_GET_CONNECTION = - JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); - - const char* C_JAVA_SQL_CONNECTION = "java/sql/Connection"; - JniMethod M_JAVA_SQL_CONNECTION_CLOSE = JniMethod("close", "()V", false); + const char* const C_RECORD_SET = "java/sql/ResultSet"; + JniMethod const M_RECORD_SET_NEXT = JniMethod("next", "()Z", false); + JniMethod const M_RECORD_SET_GET_STRING_BY_INDEX = + JniMethod( + "getString", + "(I)Ljava/lang/String;", false); + JniMethod const M_RECORD_SET_GET_STRING_BY_NAME = + JniMethod( + "getString", + "(Ljava/lang/String;)Ljava/lang/String;", false); + JniMethod const M_RECORD_SET_GET_INTEGER_BY_INDEX = + JniMethod( + "getInt", + "(I)I", false); + JniMethod const M_RECORD_SET_GET_INTEGER_BY_NAME = + JniMethod( + "getInt", + "(Ljava/lang/String;)I", false); + JniMethod const M_RECORD_SET_WAS_NULL = + JniMethod( + "wasNull", + "()Z", false); + + const char* const C_DATABASE_META_DATA = "java/sql/DatabaseMetaData"; + JniMethod const M_DATABASE_META_DATA_GET_TABLES = + JniMethod("getTables", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Ljava/sql/ResultSet;", + false); + + const char* const C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; + + const char* const C_DRIVERMANAGER = "java/sql/DriverManager"; + JniMethod const M_DRIVERMANAGER_GET_CONNECTION = + JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); + + const char* const C_JAVA_SQL_CONNECTION = "java/sql/Connection"; + JniMethod const M_JAVA_SQL_CONNECTION_CLOSE = JniMethod("close", "()V", false); + JniMethod const M_JAVA_SQL_CONNECTION_GET_META_DATA = + JniMethod("getMetaData", + "()Ljava/sql/DatabaseMetaData;", false); // TODO: Provide a "getFullStackTrace" from DocumentDB //JniMethod M_PLATFORM_UTILS_GET_FULL_STACK_TRACE = JniMethod("getFullStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;", true); @@ -432,8 +496,20 @@ namespace ignite c_DriverManager = FindClass(env, C_DRIVERMANAGER); m_DriverManagerGetConnection = FindMethod(env, c_DriverManager, M_DRIVERMANAGER_GET_CONNECTION); - c_JavaSqlConnection = FindClass(env, C_JAVA_SQL_CONNECTION); - m_JavaSqlConnectionClose = FindMethod(env, c_JavaSqlConnection, M_JAVA_SQL_CONNECTION_CLOSE); + c_ResultSet = FindClass(env, C_RECORD_SET); + m_ResultSetNext = FindMethod(env, c_ResultSet, M_RECORD_SET_NEXT); + m_ResultSetGetStringByIndex = FindMethod(env, c_ResultSet, M_RECORD_SET_GET_STRING_BY_INDEX); + m_ResultSetGetStringByName = FindMethod(env, c_ResultSet, M_RECORD_SET_GET_STRING_BY_NAME); + m_ResultSetGetIntegerByIndex = FindMethod(env, c_ResultSet, M_RECORD_SET_GET_INTEGER_BY_INDEX); + m_ResultSetGetIntegerByName = FindMethod(env, c_ResultSet, M_RECORD_SET_GET_INTEGER_BY_NAME); + m_ResultSetWasNull = FindMethod(env, c_ResultSet, M_RECORD_SET_WAS_NULL); + + c_DatabaseMetaData = FindClass(env, C_DATABASE_META_DATA); + m_DatabaseMetaDataGetTables = FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_TABLES); + + c_Connection = FindClass(env, C_JAVA_SQL_CONNECTION); + m_ConnectionClose = FindMethod(env, c_Connection, M_JAVA_SQL_CONNECTION_CLOSE); + m_ConnectionGetMetaData = FindMethod(env, c_Connection, M_JAVA_SQL_CONNECTION_GET_META_DATA); } void JniMembers::Destroy(JNIEnv* env) { @@ -469,6 +545,19 @@ namespace ignite return members; } + GlobalJObject::GlobalJObject(JNIEnv* e, jobject obj) : env(e), ref(obj) { + // No-op. + } + + GlobalJObject::~GlobalJObject() { + env->DeleteGlobalRef(ref); + } + + jobject GlobalJObject::GetRef() const { + return ref; + } + + /** * Create JVM. */ @@ -508,23 +597,18 @@ namespace ignite } void RegisterNatives(JNIEnv* env) { - { - JNINativeMethod methods[5]; - - int idx = 0; - - // TODO: Investigate registering callbacks to get console and logging streams. - - //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_CONSOLE_WRITE, reinterpret_cast(JniConsoleWrite)); - - //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_LOG, reinterpret_cast(JniLoggerLog)); - //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_IS_LEVEL_ENABLED, reinterpret_cast(JniLoggerIsLevelEnabled)); - - //jint res = env->RegisterNatives(FindClass(env, C_PLATFORM_CALLBACK_UTILS), methods, idx); - - //if (res != JNI_OK) - // throw JvmException(); - } + // TODO: Investigate registering callbacks to get console and logging streams. + + // JNINativeMethod methods[5]; + // int idx = 0; + // AddNativeMethod(methods + idx++, + // M_PLATFORM_CALLBACK_UTILS_CONSOLE_WRITE, + // reinterpret_cast(JniConsoleWrite)); + // AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_LOG, reinterpret_cast(JniLoggerLog)); + // AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_IS_LEVEL_ENABLED, reinterpret_cast(JniLoggerIsLevelEnabled)); + // jint res = env->RegisterNatives(FindClass(env, C_PLATFORM_CALLBACK_UTILS), methods, idx); + // if (res != JNI_OK) + // throw JvmException(); } JniContext::JniContext(JniJvm* jvm, JniHandlers hnds) : jvm(jvm), hnds(hnds) { @@ -721,29 +805,250 @@ namespace ignite } } - jobject JniContext::DocumentDbConnect(const char* connectionString, - JniErrorInfo* errInfo) { + bool JniContext::DriverManagerGetConnection( + const char* connectionString, + SharedPointer< GlobalJObject >& connection, + JniErrorInfo* errInfo) { JNIEnv* env = Attach(); - jstring jConnectionString = - env->NewStringUTF(connectionString); - jobject connection = env->CallStaticObjectMethod( + jstring jConnectionString = env->NewStringUTF(connectionString); + jobject result = env->CallStaticObjectMethod( jvm->GetMembers().c_DriverManager, - jvm->GetMembers().m_DriverManagerGetConnection, jConnectionString); + jvm->GetMembers().m_DriverManagerGetConnection, + jConnectionString); ExceptionCheck(env, errInfo); - return connection; + if (!result) { + connection = SharedPointer< GlobalJObject >(nullptr); + return false; + } + connection = SharedPointer< GlobalJObject >(new GlobalJObject(env, env->NewGlobalRef(result))); + return true; } - void JniContext::DocumentDbDisconnect(const jobject connection, JniErrorInfo* errInfo) { - if (!connection) { + void JniContext::ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo) { + if (!connection.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "Connection object must be set."; return; } JNIEnv* env = Attach(); - env->CallVoidMethod(connection, jvm->GetMembers().m_JavaSqlConnectionClose); + env->CallVoidMethod(connection.Get()->GetRef(), + jvm->GetMembers().m_ConnectionClose); + ExceptionCheck(env, errInfo); + } + + bool JniContext::ConnectionGetMetaData( + const SharedPointer< GlobalJObject >& connection, + SharedPointer< GlobalJObject >& databaseMetaData, + JniErrorInfo* errInfo) { + if (!connection.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "Connection object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jobject result = env->CallObjectMethod( + connection.Get()->GetRef(), + jvm->GetMembers().m_ConnectionGetMetaData); + ExceptionCheck(env, errInfo); + + if (!result || errInfo->code != IGNITE_JNI_ERR_SUCCESS) { + databaseMetaData = SharedPointer< GlobalJObject >(nullptr); + return false; + } + + databaseMetaData = SharedPointer< GlobalJObject >( + new GlobalJObject(env, env->NewGlobalRef(result))); + return true; + } + + bool JniContext::DatabaseMetaDataGetTables( + const SharedPointer< GlobalJObject >& databaseMetaData, + SharedPointer< GlobalJObject >& resultSet, + JniErrorInfo* errInfo) { + if (!databaseMetaData.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "DatabaseMetaData object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jobject result = env->CallObjectMethod( + databaseMetaData.Get()->GetRef(), + jvm->GetMembers().m_DatabaseMetaDataGetTables, + /* catalog */ nullptr, + /* schemaPattern */ nullptr, + /* tableNamePattern */ nullptr, + /* types[]*/ nullptr); + ExceptionCheck(env, errInfo); + + if (!result || errInfo->code != IGNITE_JNI_ERR_SUCCESS) { + resultSet = SharedPointer< GlobalJObject >(nullptr); + return false; + } + + resultSet = SharedPointer< GlobalJObject >( + new GlobalJObject(env, env->NewGlobalRef(result))); + return true; + } + + bool JniContext::ResultSetNext( + const SharedPointer< GlobalJObject >& resultSet, + bool& hasNext, JniErrorInfo* errInfo) { + if (!resultSet.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jboolean res = env->CallBooleanMethod( + resultSet.Get()->GetRef(), + jvm->GetMembers().m_ResultSetNext); + ExceptionCheck(env, errInfo); + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + hasNext = res != JNI_TRUE; + } + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetGetString(const jobject resultSet, + int columnIndex, + std::string& value, + bool& wasNull, + JniErrorInfo* errInfo) { + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jobject result = env->CallObjectMethod( + resultSet, jvm->GetMembers().m_ResultSetGetStringByIndex, + columnIndex); + ExceptionCheck(env, errInfo); + + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + wasNull = !result; + if (result != nullptr) { + jboolean isCopy; + const char* utfChars = env->GetStringUTFChars( + (jstring)result, &isCopy); + value = std::string(utfChars); + env->ReleaseStringUTFChars((jstring)result, + utfChars); + } + } + + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetGetString(const jobject resultSet, + const std::string& columnName, + std::string& value, + bool& wasNull, + JniErrorInfo* errInfo) { + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jobject result = env->CallObjectMethod( + resultSet, jvm->GetMembers().m_ResultSetGetStringByName, + columnName); ExceptionCheck(env, errInfo); - env->DeleteLocalRef(connection); + + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + wasNull = !result; + if (result != nullptr) { + jboolean isCopy; + const char* utfChars = env->GetStringUTFChars( + (jstring)result, &isCopy); + value = std::string(utfChars); + env->ReleaseStringUTFChars((jstring)result, + utfChars); + } + } + + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetGetInteger(const jobject resultSet, + int columnIndex, + int& value, + bool& wasNull, + JniErrorInfo* errInfo) { + + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jint result = env->CallIntMethod( + resultSet, + jvm->GetMembers().m_ResultSetGetIntegerByIndex, + columnIndex); + ExceptionCheck(env, errInfo); + + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + value = result; + return ResultSetWasNull(resultSet, wasNull, errInfo); + } + + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetGetInteger(const jobject resultSet, + const std::string& columnName, + int& value, + bool& wasNull, + JniErrorInfo* errInfo) { + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jint result = env->CallIntMethod( + resultSet, + jvm->GetMembers().m_ResultSetGetIntegerByName, + columnName); + ExceptionCheck(env, errInfo); + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + value = result; + return ResultSetWasNull(resultSet, wasNull, errInfo); + } + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetWasNull(const jobject resultSet, + bool& value, + JniErrorInfo* errInfo) { + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + bool res = env->CallBooleanMethod( + resultSet, jvm->GetMembers().m_ResultSetWasNull); + ExceptionCheck(env, errInfo); + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + value = res; + } + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; } - int64_t JniContext::TargetInLongOutLong(jobject obj, int opType, int64_t val, JniErrorInfo* err) { + int64_t JniContext::TargetInLongOutLong(jobject obj, int opType, + int64_t val, + JniErrorInfo* err) { JNIEnv* env = Attach(); int64_t res = env->CallLongMethod(obj, jvm->GetMembers().m_PlatformTarget_inLongOutLong, opType, val); diff --git a/src/odbc/src/jni/os/linux/utils.cpp b/src/odbc/src/jni/os/linux/utils.cpp index 6fd4d6e7a..fcb4a7d41 100644 --- a/src/odbc/src/jni/os/linux/utils.cpp +++ b/src/odbc/src/jni/os/linux/utils.cpp @@ -24,8 +24,8 @@ #include #include -#include "ignite/common/utils.h" -#include "ignite/common/fixed_size_array.h" +#include "ignite/odbc/common/utils.h" +#include "ignite/odbc/common/fixed_size_array.h" #include "ignite/odbc/jni/utils.h" #include "ignite/odbc/jni/java.h" diff --git a/src/odbc/src/jni/os/win/utils.cpp b/src/odbc/src/jni/os/win/utils.cpp index e41fb56af..ddeb05c59 100644 --- a/src/odbc/src/jni/os/win/utils.cpp +++ b/src/odbc/src/jni/os/win/utils.cpp @@ -18,15 +18,15 @@ #include #include -#include "ignite/common/concurrent.h" -#include "ignite/common/utils.h" -#include "ignite/common/fixed_size_array.h" +#include "ignite/odbc/common/concurrent.h" +#include "ignite/odbc/common/utils.h" +#include "ignite/odbc/common/fixed_size_array.h" #include "ignite/odbc/jni/utils.h" #include "ignite/odbc/jni/java.h" -using namespace ignite::common; -using namespace ignite::common::concurrent; +using namespace ignite::odbc::common; +using namespace ignite::odbc::common::concurrent; using namespace ignite::odbc::jni::java; @@ -409,7 +409,7 @@ namespace ignite return home; // 3. Check current work dir. - DWORD curDirLen = GetCurrentDirectoryA(0, NULL); + DWORD curDirLen = GetCurrentDirectoryA(0, nullptr); if (!curDirLen) return std::string(); From 3ad4c66d61e08331757c66c7d3e2c1d36d8fb96b Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 09:25:37 -0800 Subject: [PATCH 101/165] [AD-427] Fix Mac build. --- src/odbc/src/jni/java.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 573c499be..ee5077582 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -956,9 +956,10 @@ namespace ignite } JNIEnv* env = Attach(); + jstring jColumnName = env->NewStringUTF(columnName.c_str()); jobject result = env->CallObjectMethod( resultSet, jvm->GetMembers().m_ResultSetGetStringByName, - columnName); + jColumnName); ExceptionCheck(env, errInfo); if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { @@ -1015,10 +1016,11 @@ namespace ignite } JNIEnv* env = Attach(); + jstring jColumnName = env->NewStringUTF(columnName.c_str()); jint result = env->CallIntMethod( resultSet, jvm->GetMembers().m_ResultSetGetIntegerByName, - columnName); + jColumnName); ExceptionCheck(env, errInfo); if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { value = result; From 460ac614a10100afc4508e4431daedf53941e285 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 09:34:24 -0800 Subject: [PATCH 102/165] [AD-427] Fix Mac build. --- src/odbc/src/jni/os/linux/utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc/src/jni/os/linux/utils.cpp b/src/odbc/src/jni/os/linux/utils.cpp index fcb4a7d41..a4ab1f47e 100644 --- a/src/odbc/src/jni/os/linux/utils.cpp +++ b/src/odbc/src/jni/os/linux/utils.cpp @@ -30,7 +30,7 @@ #include "ignite/odbc/jni/utils.h" #include "ignite/odbc/jni/java.h" -using namespace ignite::common; +using namespace ignite::odbc::common; using namespace ignite::odbc::jni::java; namespace ignite From af5780fed1693adc5ecadf1f091d8df67dfb79d5 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 09:46:41 -0800 Subject: [PATCH 103/165] [AD-427] Fix Windows build. --- scripts/build_driver.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/build_driver.ps1 b/scripts/build_driver.ps1 index 7a38234d1..f6211738d 100644 --- a/scripts/build_driver.ps1 +++ b/scripts/build_driver.ps1 @@ -19,6 +19,7 @@ $CMAKE_TOOLCHAIN_FILE = -join($env:VCPKG_ROOT, "/scripts/buildsystems/vcpkg.cmak cmake -S $SRC_DIR ` -B $BUILD_DIR ` -A $WIN_ARCH ` + -G "Visual Studio 15 2017" -D CMAKE_BUILD_TYPE=$CONFIGURATION ` -D CMAKE_INSTALL_PREFIX=$INSTALL_DIR ` -D WITH_TESTS=ON ` From 1f52bc2966b43331ee83ea0ffb1cbba71a37a1bb Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 10:04:20 -0800 Subject: [PATCH 104/165] [AD-427] Fix Windows build. --- scripts/build_driver.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/build_driver.ps1 b/scripts/build_driver.ps1 index f6211738d..7a38234d1 100644 --- a/scripts/build_driver.ps1 +++ b/scripts/build_driver.ps1 @@ -19,7 +19,6 @@ $CMAKE_TOOLCHAIN_FILE = -join($env:VCPKG_ROOT, "/scripts/buildsystems/vcpkg.cmak cmake -S $SRC_DIR ` -B $BUILD_DIR ` -A $WIN_ARCH ` - -G "Visual Studio 15 2017" -D CMAKE_BUILD_TYPE=$CONFIGURATION ` -D CMAKE_INSTALL_PREFIX=$INSTALL_DIR ` -D WITH_TESTS=ON ` From 0e2afc3b7b7680bd5d6e43641c000ab44338c0e5 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 11:07:07 -0800 Subject: [PATCH 105/165] [AD-427] Fix Windows build. --- .github/workflows/win-build.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index b02b4b8f5..4b7202684 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -49,8 +49,8 @@ jobs: run: | echo "C:\Program Files (x86)\WiX Toolset v3.11\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Get specific version CMake, v3.20.1 - uses: lukka/get-cmake@v3.20.1 + - name: Get latest version CMake + uses: lukka/get-cmake@latest - name: add-msbuild-to-path uses: microsoft/setup-msbuild@v1.0.2 @@ -137,8 +137,8 @@ jobs: run: | echo "C:\Program Files (x86)\WiX Toolset v3.11\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Get specific version CMake, v3.20.1 - uses: lukka/get-cmake@v3.20.1 + - name: Get latest version CMake + uses: lukka/get-cmake@latest - name: add-msbuild-to-path uses: microsoft/setup-msbuild@v1.0.2 @@ -212,8 +212,8 @@ jobs: # - name: "Update path for Java" # run: | # echo "${{ env.JAVA_HOME }}\bin\server" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - # - name: Get specific version CMake, v3.20.1 - # uses: lukka/get-cmake@v3.20.1 + # - name: Get latest version CMake + # uses: lukka/get-cmake@latest # - name: add-msbuild-to-path # uses: microsoft/setup-msbuild@v1.0.2 # - name: setup-opencppcoverage-and-add-to-path From 2355e5c60e367d8d456d49dc9d28fc069bf09d2e Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 1 Feb 2022 11:43:43 -0800 Subject: [PATCH 106/165] [AD-522] remove space and add new line at the end of enum types --- src/odbc/include/ignite/odbc/read_preference.h | 11 +++-------- src/odbc/include/ignite/odbc/scan_method.h | 10 +++------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/odbc/include/ignite/odbc/read_preference.h b/src/odbc/include/ignite/odbc/read_preference.h index 5053c3ba5..b355335ac 100644 --- a/src/odbc/include/ignite/odbc/read_preference.h +++ b/src/odbc/include/ignite/odbc/read_preference.h @@ -29,15 +29,10 @@ namespace ignite enum Type { PRIMARY, - PRIMARY_PREFERRED, - - SECONDARY, - + SECONDARY, SECONDARY_PREFERRED, - - NEAREST, - + NEAREST, UNKNOWN }; @@ -62,4 +57,4 @@ namespace ignite } } -#endif //_IGNITE_ODBC_READ_PREFERENCE \ No newline at end of file +#endif //_IGNITE_ODBC_READ_PREFERENCE diff --git a/src/odbc/include/ignite/odbc/scan_method.h b/src/odbc/include/ignite/odbc/scan_method.h index 0260fba6a..d81df80ff 100644 --- a/src/odbc/include/ignite/odbc/scan_method.h +++ b/src/odbc/include/ignite/odbc/scan_method.h @@ -29,13 +29,9 @@ namespace ignite enum Type { RANDOM, - ID_FORWARD, - - ID_REVERSE, - - ALL, - + ID_REVERSE, + ALL, UNKNOWN }; @@ -59,4 +55,4 @@ namespace ignite }; } } // namespace ignite -#endif //_IGNITE_ODBC_SCAN_METHOD \ No newline at end of file +#endif //_IGNITE_ODBC_SCAN_METHOD From 55132cf8e0f46bcd78bb13583152f6db2f8c3e1d Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 1 Feb 2022 11:45:52 -0800 Subject: [PATCH 107/165] [AD-522] add new lines at the end of Enum type files --- src/odbc/include/ignite/odbc/read_preference.h | 1 + src/odbc/include/ignite/odbc/scan_method.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/odbc/include/ignite/odbc/read_preference.h b/src/odbc/include/ignite/odbc/read_preference.h index b355335ac..a05916eab 100644 --- a/src/odbc/include/ignite/odbc/read_preference.h +++ b/src/odbc/include/ignite/odbc/read_preference.h @@ -58,3 +58,4 @@ namespace ignite } #endif //_IGNITE_ODBC_READ_PREFERENCE + diff --git a/src/odbc/include/ignite/odbc/scan_method.h b/src/odbc/include/ignite/odbc/scan_method.h index d81df80ff..70b24b835 100644 --- a/src/odbc/include/ignite/odbc/scan_method.h +++ b/src/odbc/include/ignite/odbc/scan_method.h @@ -56,3 +56,4 @@ namespace ignite } } // namespace ignite #endif //_IGNITE_ODBC_SCAN_METHOD + From 749a1c8dea19f7b889c0f9564ba5e53b5d63a593 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 13:16:42 -0800 Subject: [PATCH 108/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 44a469c8f..01866de6f 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -116,7 +116,8 @@ endif() add_executable(${TARGET} ${SOURCES}) target_link_libraries(${TARGET} ${ODBC_LIBRARIES}) -target_link_libraries(${TARGET} ${Boost_LIBRARIES} ignite ${ODBC_LIBRARY}) +target_link_libraries(${TARGET} ${ODBC_LIBRARY}) +target_link_libraries(${TARGET} ${Boost_LIBRARIES} ignite) target_code_coverage(${TARGET} PUBLIC AUTO ALL) if (WIN32) @@ -127,7 +128,8 @@ if (WIN32) endif() else() - add_definitions(-DBOOST_TEST_DYN_LINK) + add_definitions(-DBOOST_TEST_DYN_LINK)] + target_link_libraries(${TARGET} odbccp32) endif() set(TEST_TARGET IgniteOdbcTest) From 37acdf11d9102bd255b2d1f77edacd3c4c7e995e Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 13:20:46 -0800 Subject: [PATCH 109/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 01866de6f..36c4d3bad 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -128,7 +128,7 @@ if (WIN32) endif() else() - add_definitions(-DBOOST_TEST_DYN_LINK)] + add_definitions(-DBOOST_TEST_DYN_LINK) target_link_libraries(${TARGET} odbccp32) endif() From e6df2db401330c81b30fb9be4418d849f75fe509 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 13:38:25 -0800 Subject: [PATCH 110/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 36c4d3bad..70f1631e8 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -129,7 +129,7 @@ if (WIN32) else() add_definitions(-DBOOST_TEST_DYN_LINK) - target_link_libraries(${TARGET} odbccp32) + target_link_libraries(${TARGET} odbcinst) endif() set(TEST_TARGET IgniteOdbcTest) From 22bf6f317967baee79319ab5a8cc9e533a6610a5 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 13:57:10 -0800 Subject: [PATCH 111/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 70f1631e8..f1eb7fdb1 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -129,7 +129,7 @@ if (WIN32) else() add_definitions(-DBOOST_TEST_DYN_LINK) - target_link_libraries(${TARGET} odbcinst) + target_link_libraries(${TARGET} odbc) endif() set(TEST_TARGET IgniteOdbcTest) From d85c63f257bf54a383cb83792a02d703bca23add Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 14:08:00 -0800 Subject: [PATCH 112/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index f1eb7fdb1..103103d74 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -129,7 +129,7 @@ if (WIN32) else() add_definitions(-DBOOST_TEST_DYN_LINK) - target_link_libraries(${TARGET} odbc) + target_link_libraries(${TARGET} libodbc) endif() set(TEST_TARGET IgniteOdbcTest) From 0d048131f2ee2856ae22cfd73b3011c163fd9169 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 14:15:19 -0800 Subject: [PATCH 113/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 103103d74..668eddff9 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -129,7 +129,6 @@ if (WIN32) else() add_definitions(-DBOOST_TEST_DYN_LINK) - target_link_libraries(${TARGET} libodbc) endif() set(TEST_TARGET IgniteOdbcTest) From af198102136858a17e3b74ba347cd1c256571972 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Tue, 1 Feb 2022 14:33:49 -0800 Subject: [PATCH 114/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 668eddff9..49533a7ca 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -129,6 +129,7 @@ if (WIN32) else() add_definitions(-DBOOST_TEST_DYN_LINK) + target_link_libraries(${TARGET} libodbcinst) endif() set(TEST_TARGET IgniteOdbcTest) From 81d13024148b8c19f7100cea2357caf27a4691ad Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 2 Feb 2022 10:23:19 -0800 Subject: [PATCH 115/165] [AD-521] add changes for Java.cpp from Bruce's AD-427 branch * those changes are not included in the previous merge, and are now added --- src/odbc/src/jni/java.cpp | 464 +++++++++++++++++++++++++++++++------- 1 file changed, 382 insertions(+), 82 deletions(-) diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 58ce058fc..ee5077582 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -23,11 +23,13 @@ #include #include +#include #include +#include #include #include -#include -#include + +using namespace ignite::odbc::common::concurrent; #ifndef JNI_VERSION_9 #define JNI_VERSION_9 0x00090000 @@ -114,9 +116,63 @@ namespace ignite return JNI_GetDefaultJavaVMInitArgs(&args) == JNI_OK; } + void BuildJvmOptions( + const std::string& cp, std::vector< char* >& opts, + int xms, int xmx) { + using namespace common; + + const size_t REQ_OPTS_CNT = 4; + const size_t JAVA9_OPTS_CNT = 6; + + opts.reserve(REQ_OPTS_CNT + JAVA9_OPTS_CNT); + + // 1. Set classpath. + std::string cpFull = "-Djava.class.path=" + cp; + + opts.push_back(CopyChars(cpFull.c_str())); + + // 3. Set Xms, Xmx. + std::string xmsStr = "-Xms" + std::to_string(xms) + "m"; + std::string xmxStr = "-Xmx" + std::to_string(xmx) + "m"; + + opts.push_back(CopyChars(xmsStr.c_str())); + opts.push_back(CopyChars(xmxStr.c_str())); + + // 4. Optional debug arguments + // std::string debugStr = + // "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"; + // opts.push_back(CopyChars(debugStr.c_str())); + + // 5. Set file.encoding. + std::string fileEncParam = "-Dfile.encoding="; + std::string fileEncFull = fileEncParam + "UTF-8"; + opts.push_back(CopyChars(fileEncFull.c_str())); + + // Adding options for Java 9 or later + if (jni::java::IsJava9OrLater()) { + opts.push_back( + CopyChars("--add-exports=java.base/" + "jdk.internal.misc=ALL-UNNAMED")); + opts.push_back(CopyChars( + "--add-exports=java.base/sun.nio.ch=ALL-UNNAMED")); + opts.push_back( + CopyChars("--add-exports=java.management/" + "com.sun.jmx.mbeanserver=ALL-UNNAMED")); + opts.push_back( + CopyChars("--add-exports=jdk.internal.jvmstat/" + "sun.jvmstat.monitor=ALL-UNNAMED")); + opts.push_back( + CopyChars("--add-exports=java.base/" + "sun.reflect.generics.reflectiveObjects=" + "ALL-UNNAMED")); + opts.push_back(CopyChars( + "--add-opens=jdk.management/" + "com.sun.management.internal=ALL-UNNAMED")); + } + } + /* --- Startup exception. --- */ - class JvmException : public std::exception - { + class JvmException : public std::exception { // No-op. }; @@ -172,60 +228,62 @@ namespace ignite delete[] errMsg; } - /** - * Guard to ensure global reference cleanup. - */ - class JniGlobalRefGuard - { - public: - JniGlobalRefGuard(JNIEnv *e, jobject obj) : env(e), ref(obj) - { - // No-op. - } - - ~JniGlobalRefGuard() - { - env->DeleteGlobalRef(ref); - } - - private: - /** Environment. */ - JNIEnv* env; - - /** Target reference. */ - jobject ref; - - IGNITE_NO_COPY_ASSIGNMENT(JniGlobalRefGuard); - }; - - const char* C_THROWABLE = "java/lang/Throwable"; - JniMethod M_THROWABLE_GET_MESSAGE = JniMethod("getMessage", "()Ljava/lang/String;", false); - JniMethod M_THROWABLE_PRINT_STACK_TRACE = JniMethod("printStackTrace", "()V", false); + // Classes and method definitions. + const char* const C_THROWABLE = "java/lang/Throwable"; + JniMethod const M_THROWABLE_GET_MESSAGE = JniMethod("getMessage", "()Ljava/lang/String;", false); + JniMethod const M_THROWABLE_PRINT_STACK_TRACE = JniMethod("printStackTrace", "()V", false); - const char* C_CLASS = "java/lang/Class"; - JniMethod M_CLASS_GET_NAME = JniMethod("getName", "()Ljava/lang/String;", false); + const char* const C_CLASS = "java/lang/Class"; + JniMethod const M_CLASS_GET_NAME = JniMethod("getName", "()Ljava/lang/String;", false); - const char* C_DOCUMENTDB_CONNECTION_PROPERTIES = + const char* const C_DOCUMENTDB_CONNECTION_PROPERTIES = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; - JniMethod M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING = + JniMethod const M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING = JniMethod( "getPropertiesFromConnectionString", "(Ljava/lang/String;)Lsoftware/amazon/documentdb/jdbc/DocumentDbConnectionProperties;", true); - // todo code draft -AL-. After constants all defined (define constants here), work on the JNI wrappers with Bruce - const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnection"; - JniMethod M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT = - JniMethod("getSshLocalPort", "()I", false); - - // const char* C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; - - const char* C_DRIVERMANAGER = "java/sql/DriverManager"; - JniMethod M_DRIVERMANAGER_GET_CONNECTION = - JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); // -AL- true/false defines whether it is true -> static/instance - - const char* C_JAVA_SQL_CONNECTION = "java/sql/Connection"; - JniMethod M_JAVA_SQL_CONNECTION_CLOSE = JniMethod("close", "()V", false); + const char* const C_RECORD_SET = "java/sql/ResultSet"; + JniMethod const M_RECORD_SET_NEXT = JniMethod("next", "()Z", false); + JniMethod const M_RECORD_SET_GET_STRING_BY_INDEX = + JniMethod( + "getString", + "(I)Ljava/lang/String;", false); + JniMethod const M_RECORD_SET_GET_STRING_BY_NAME = + JniMethod( + "getString", + "(Ljava/lang/String;)Ljava/lang/String;", false); + JniMethod const M_RECORD_SET_GET_INTEGER_BY_INDEX = + JniMethod( + "getInt", + "(I)I", false); + JniMethod const M_RECORD_SET_GET_INTEGER_BY_NAME = + JniMethod( + "getInt", + "(Ljava/lang/String;)I", false); + JniMethod const M_RECORD_SET_WAS_NULL = + JniMethod( + "wasNull", + "()Z", false); + + const char* const C_DATABASE_META_DATA = "java/sql/DatabaseMetaData"; + JniMethod const M_DATABASE_META_DATA_GET_TABLES = + JniMethod("getTables", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Ljava/sql/ResultSet;", + false); + + const char* const C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; + + const char* const C_DRIVERMANAGER = "java/sql/DriverManager"; + JniMethod const M_DRIVERMANAGER_GET_CONNECTION = + JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); + + const char* const C_JAVA_SQL_CONNECTION = "java/sql/Connection"; + JniMethod const M_JAVA_SQL_CONNECTION_CLOSE = JniMethod("close", "()V", false); + JniMethod const M_JAVA_SQL_CONNECTION_GET_META_DATA = + JniMethod("getMetaData", + "()Ljava/sql/DatabaseMetaData;", false); // TODO: Provide a "getFullStackTrace" from DocumentDB //JniMethod M_PLATFORM_UTILS_GET_FULL_STACK_TRACE = JniMethod("getFullStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;", true); @@ -434,13 +492,24 @@ namespace ignite c_DocumentDbConnection = FindClass(env, C_DOCUMENTDB_CONNECTION); //m_DocumentDbConnectionInit = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_PROPERTIES_INIT); - m_DocumentDbConnectionGetSshLocalPort = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT); c_DriverManager = FindClass(env, C_DRIVERMANAGER); m_DriverManagerGetConnection = FindMethod(env, c_DriverManager, M_DRIVERMANAGER_GET_CONNECTION); - c_JavaSqlConnection = FindClass(env, C_JAVA_SQL_CONNECTION); - m_JavaSqlConnectionClose = FindMethod(env, c_JavaSqlConnection, M_JAVA_SQL_CONNECTION_CLOSE); + c_ResultSet = FindClass(env, C_RECORD_SET); + m_ResultSetNext = FindMethod(env, c_ResultSet, M_RECORD_SET_NEXT); + m_ResultSetGetStringByIndex = FindMethod(env, c_ResultSet, M_RECORD_SET_GET_STRING_BY_INDEX); + m_ResultSetGetStringByName = FindMethod(env, c_ResultSet, M_RECORD_SET_GET_STRING_BY_NAME); + m_ResultSetGetIntegerByIndex = FindMethod(env, c_ResultSet, M_RECORD_SET_GET_INTEGER_BY_INDEX); + m_ResultSetGetIntegerByName = FindMethod(env, c_ResultSet, M_RECORD_SET_GET_INTEGER_BY_NAME); + m_ResultSetWasNull = FindMethod(env, c_ResultSet, M_RECORD_SET_WAS_NULL); + + c_DatabaseMetaData = FindClass(env, C_DATABASE_META_DATA); + m_DatabaseMetaDataGetTables = FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_TABLES); + + c_Connection = FindClass(env, C_JAVA_SQL_CONNECTION); + m_ConnectionClose = FindMethod(env, c_Connection, M_JAVA_SQL_CONNECTION_CLOSE); + m_ConnectionGetMetaData = FindMethod(env, c_Connection, M_JAVA_SQL_CONNECTION_GET_META_DATA); } void JniMembers::Destroy(JNIEnv* env) { @@ -476,6 +545,19 @@ namespace ignite return members; } + GlobalJObject::GlobalJObject(JNIEnv* e, jobject obj) : env(e), ref(obj) { + // No-op. + } + + GlobalJObject::~GlobalJObject() { + env->DeleteGlobalRef(ref); + } + + jobject GlobalJObject::GetRef() const { + return ref; + } + + /** * Create JVM. */ @@ -515,23 +597,18 @@ namespace ignite } void RegisterNatives(JNIEnv* env) { - { - JNINativeMethod methods[5]; - - int idx = 0; - - // TODO: Investigate registering callbacks to get console and logging streams. - - //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_CONSOLE_WRITE, reinterpret_cast(JniConsoleWrite)); - - //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_LOG, reinterpret_cast(JniLoggerLog)); - //AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_IS_LEVEL_ENABLED, reinterpret_cast(JniLoggerIsLevelEnabled)); - - //jint res = env->RegisterNatives(FindClass(env, C_PLATFORM_CALLBACK_UTILS), methods, idx); - - //if (res != JNI_OK) - // throw JvmException(); - } + // TODO: Investigate registering callbacks to get console and logging streams. + + // JNINativeMethod methods[5]; + // int idx = 0; + // AddNativeMethod(methods + idx++, + // M_PLATFORM_CALLBACK_UTILS_CONSOLE_WRITE, + // reinterpret_cast(JniConsoleWrite)); + // AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_LOG, reinterpret_cast(JniLoggerLog)); + // AddNativeMethod(methods + idx++, M_PLATFORM_CALLBACK_UTILS_LOGGER_IS_LEVEL_ENABLED, reinterpret_cast(JniLoggerIsLevelEnabled)); + // jint res = env->RegisterNatives(FindClass(env, C_PLATFORM_CALLBACK_UTILS), methods, idx); + // if (res != JNI_OK) + // throw JvmException(); } JniContext::JniContext(JniJvm* jvm, JniHandlers hnds) : jvm(jvm), hnds(hnds) { @@ -728,29 +805,252 @@ namespace ignite } } - jobject JniContext::DocumentDbConnect(const char* connectionString, - JniErrorInfo* errInfo) { + bool JniContext::DriverManagerGetConnection( + const char* connectionString, + SharedPointer< GlobalJObject >& connection, + JniErrorInfo* errInfo) { JNIEnv* env = Attach(); - jstring jConnectionString = - env->NewStringUTF(connectionString); - jobject connection = env->CallStaticObjectMethod( + jstring jConnectionString = env->NewStringUTF(connectionString); + jobject result = env->CallStaticObjectMethod( jvm->GetMembers().c_DriverManager, - jvm->GetMembers().m_DriverManagerGetConnection, jConnectionString); + jvm->GetMembers().m_DriverManagerGetConnection, + jConnectionString); ExceptionCheck(env, errInfo); - return connection; + if (!result) { + connection = SharedPointer< GlobalJObject >(nullptr); + return false; + } + connection = SharedPointer< GlobalJObject >(new GlobalJObject(env, env->NewGlobalRef(result))); + return true; } - void JniContext::DocumentDbDisconnect(const jobject connection, JniErrorInfo* errInfo) { - if (!connection) { + void JniContext::ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo) { + if (!connection.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "Connection object must be set."; return; } JNIEnv* env = Attach(); - env->CallVoidMethod(connection, jvm->GetMembers().m_JavaSqlConnectionClose); + env->CallVoidMethod(connection.Get()->GetRef(), + jvm->GetMembers().m_ConnectionClose); + ExceptionCheck(env, errInfo); + } + + bool JniContext::ConnectionGetMetaData( + const SharedPointer< GlobalJObject >& connection, + SharedPointer< GlobalJObject >& databaseMetaData, + JniErrorInfo* errInfo) { + if (!connection.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "Connection object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jobject result = env->CallObjectMethod( + connection.Get()->GetRef(), + jvm->GetMembers().m_ConnectionGetMetaData); + ExceptionCheck(env, errInfo); + + if (!result || errInfo->code != IGNITE_JNI_ERR_SUCCESS) { + databaseMetaData = SharedPointer< GlobalJObject >(nullptr); + return false; + } + + databaseMetaData = SharedPointer< GlobalJObject >( + new GlobalJObject(env, env->NewGlobalRef(result))); + return true; + } + + bool JniContext::DatabaseMetaDataGetTables( + const SharedPointer< GlobalJObject >& databaseMetaData, + SharedPointer< GlobalJObject >& resultSet, + JniErrorInfo* errInfo) { + if (!databaseMetaData.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "DatabaseMetaData object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jobject result = env->CallObjectMethod( + databaseMetaData.Get()->GetRef(), + jvm->GetMembers().m_DatabaseMetaDataGetTables, + /* catalog */ nullptr, + /* schemaPattern */ nullptr, + /* tableNamePattern */ nullptr, + /* types[]*/ nullptr); + ExceptionCheck(env, errInfo); + + if (!result || errInfo->code != IGNITE_JNI_ERR_SUCCESS) { + resultSet = SharedPointer< GlobalJObject >(nullptr); + return false; + } + + resultSet = SharedPointer< GlobalJObject >( + new GlobalJObject(env, env->NewGlobalRef(result))); + return true; + } + + bool JniContext::ResultSetNext( + const SharedPointer< GlobalJObject >& resultSet, + bool& hasNext, JniErrorInfo* errInfo) { + if (!resultSet.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jboolean res = env->CallBooleanMethod( + resultSet.Get()->GetRef(), + jvm->GetMembers().m_ResultSetNext); + ExceptionCheck(env, errInfo); + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + hasNext = res != JNI_TRUE; + } + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetGetString(const jobject resultSet, + int columnIndex, + std::string& value, + bool& wasNull, + JniErrorInfo* errInfo) { + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jobject result = env->CallObjectMethod( + resultSet, jvm->GetMembers().m_ResultSetGetStringByIndex, + columnIndex); + ExceptionCheck(env, errInfo); + + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + wasNull = !result; + if (result != nullptr) { + jboolean isCopy; + const char* utfChars = env->GetStringUTFChars( + (jstring)result, &isCopy); + value = std::string(utfChars); + env->ReleaseStringUTFChars((jstring)result, + utfChars); + } + } + + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetGetString(const jobject resultSet, + const std::string& columnName, + std::string& value, + bool& wasNull, + JniErrorInfo* errInfo) { + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jstring jColumnName = env->NewStringUTF(columnName.c_str()); + jobject result = env->CallObjectMethod( + resultSet, jvm->GetMembers().m_ResultSetGetStringByName, + jColumnName); + ExceptionCheck(env, errInfo); + + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + wasNull = !result; + if (result != nullptr) { + jboolean isCopy; + const char* utfChars = env->GetStringUTFChars( + (jstring)result, &isCopy); + value = std::string(utfChars); + env->ReleaseStringUTFChars((jstring)result, + utfChars); + } + } + + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetGetInteger(const jobject resultSet, + int columnIndex, + int& value, + bool& wasNull, + JniErrorInfo* errInfo) { + + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jint result = env->CallIntMethod( + resultSet, + jvm->GetMembers().m_ResultSetGetIntegerByIndex, + columnIndex); + ExceptionCheck(env, errInfo); + + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + value = result; + return ResultSetWasNull(resultSet, wasNull, errInfo); + } + + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetGetInteger(const jobject resultSet, + const std::string& columnName, + int& value, + bool& wasNull, + JniErrorInfo* errInfo) { + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + jstring jColumnName = env->NewStringUTF(columnName.c_str()); + jint result = env->CallIntMethod( + resultSet, + jvm->GetMembers().m_ResultSetGetIntegerByName, + jColumnName); + ExceptionCheck(env, errInfo); + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + value = result; + return ResultSetWasNull(resultSet, wasNull, errInfo); + } + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + + bool JniContext::ResultSetWasNull(const jobject resultSet, + bool& value, + JniErrorInfo* errInfo) { + if (!resultSet) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "ResultSet object must be set."; + return false; + } + + JNIEnv* env = Attach(); + bool res = env->CallBooleanMethod( + resultSet, jvm->GetMembers().m_ResultSetWasNull); ExceptionCheck(env, errInfo); - env->DeleteLocalRef(connection); + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + value = res; + } + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; } - int64_t JniContext::TargetInLongOutLong(jobject obj, int opType, int64_t val, JniErrorInfo* err) { + int64_t JniContext::TargetInLongOutLong(jobject obj, int opType, + int64_t val, + JniErrorInfo* err) { JNIEnv* env = Attach(); int64_t res = env->CallLongMethod(obj, jvm->GetMembers().m_PlatformTarget_inLongOutLong, opType, val); From 77e9489a3ff9dc2ccb04a724ae5e28cc8728298b Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Wed, 2 Feb 2022 10:46:22 -0800 Subject: [PATCH 116/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 49533a7ca..1c0782395 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -116,7 +116,6 @@ endif() add_executable(${TARGET} ${SOURCES}) target_link_libraries(${TARGET} ${ODBC_LIBRARIES}) -target_link_libraries(${TARGET} ${ODBC_LIBRARY}) target_link_libraries(${TARGET} ${Boost_LIBRARIES} ignite) target_code_coverage(${TARGET} PUBLIC AUTO ALL) From f8a7225abee0337b0e882da998d2a11d8dbee8b6 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Wed, 2 Feb 2022 11:02:26 -0800 Subject: [PATCH 117/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 1c0782395..96bde3c61 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -128,7 +128,7 @@ if (WIN32) else() add_definitions(-DBOOST_TEST_DYN_LINK) - target_link_libraries(${TARGET} libodbcinst) + target_link_libraries(${TARGET} odbcinst) endif() set(TEST_TARGET IgniteOdbcTest) From db8a769a4c7d4f75bfc187389a664972091ec32a Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Wed, 2 Feb 2022 11:39:06 -0800 Subject: [PATCH 118/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 96bde3c61..94e65eaee 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -128,7 +128,7 @@ if (WIN32) else() add_definitions(-DBOOST_TEST_DYN_LINK) - target_link_libraries(${TARGET} odbcinst) + target_link_libraries(${TARGET} iodbcinst) endif() set(TEST_TARGET IgniteOdbcTest) From 49085ee0e8c7f35fb2edd6e325d14e05bcb6681d Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Wed, 2 Feb 2022 12:12:37 -0800 Subject: [PATCH 119/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 94e65eaee..1842c3d45 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -124,11 +124,12 @@ if (WIN32) add_definitions(-DTARGET_MODULE_FULL_NAME="$") if (MSVC_VERSION GREATER_EQUAL 1900) target_link_libraries(${TARGET} legacy_stdio_definitions odbccp32 shlwapi) - endif() - -else() +else(APPLE) add_definitions(-DBOOST_TEST_DYN_LINK) target_link_libraries(${TARGET} iodbcinst) +else() + add_definitions(-DBOOST_TEST_DYN_LINK) + target_link_libraries(${TARGET} odbcinst) endif() set(TEST_TARGET IgniteOdbcTest) From 09e1f3006a324fa0c7958c94eb982cf0f4a312fc Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Wed, 2 Feb 2022 12:16:45 -0800 Subject: [PATCH 120/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 1842c3d45..99e86720b 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -124,7 +124,7 @@ if (WIN32) add_definitions(-DTARGET_MODULE_FULL_NAME="$") if (MSVC_VERSION GREATER_EQUAL 1900) target_link_libraries(${TARGET} legacy_stdio_definitions odbccp32 shlwapi) -else(APPLE) +elseif(APPLE) add_definitions(-DBOOST_TEST_DYN_LINK) target_link_libraries(${TARGET} iodbcinst) else() From e5eb2dc96da86d77e5ce8fdd4719e32f3bd1af29 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Wed, 2 Feb 2022 12:22:03 -0800 Subject: [PATCH 121/165] [AD-427] Fix Mac build. --- src/odbc-test/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 99e86720b..8edf04dbc 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -124,6 +124,7 @@ if (WIN32) add_definitions(-DTARGET_MODULE_FULL_NAME="$") if (MSVC_VERSION GREATER_EQUAL 1900) target_link_libraries(${TARGET} legacy_stdio_definitions odbccp32 shlwapi) + endif() elseif(APPLE) add_definitions(-DBOOST_TEST_DYN_LINK) target_link_libraries(${TARGET} iodbcinst) From b29dd7173afd0e1877c488145536b4f19a89e1a2 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 2 Feb 2022 13:46:45 -0800 Subject: [PATCH 122/165] [AD-521] JNI wrapper calls to iSshTunnelActive and getSshLocalPort * some draft comments are left to be cleaned up --- src/odbc/include/ignite/odbc/jni/java.h | 4 ++ src/odbc/src/jni/java.cpp | 59 +++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index 02fdaae05..c7f49719b 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -257,6 +257,7 @@ namespace ignite { jclass c_DocumentDbConnection; jmethodID m_DocumentDbConnectionGetSshLocalPort; + jmethodID m_DocumentDbConnectionIsSshTunnelActive; jmethodID m_DocumentDbConnectionInit; jmethodID m_DocumentDbClose; @@ -446,6 +447,9 @@ namespace ignite { void ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo); bool ConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject>& databaseMetaData, JniErrorInfo* errInfo); + bool DocumentDbIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo* errInfo); + int32_t DocumentDbGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo); + bool DatabaseMetaDataGetTables(const SharedPointer< GlobalJObject >& databaseMetaData, SharedPointer< GlobalJObject >& resultSet, JniErrorInfo* errInfo); bool ResultSetNext(const SharedPointer< GlobalJObject >& resultSet, bool& hasNext, diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index ee5077582..dc562f593 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -274,6 +274,14 @@ namespace ignite false); const char* const C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; + // todo code draft -AL-. After constants all defined (define + // constants here), work on the JNI wrappers with Bruce + JniMethod const M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT = + JniMethod("getSshLocalPort", "()Ljava/util/Optional;", false); +// JniMethod("getSshLocalPort", "()Ljava/util/Optional;", false); + // todo add call for isSshTunnelActive + JniMethod const M_DOCUMENTDB_CONNECTION_IS_SSH_TUNNEL_ACTIVE = + JniMethod("isSshTunnelActive", "()B", false); const char* const C_DRIVERMANAGER = "java/sql/DriverManager"; JniMethod const M_DRIVERMANAGER_GET_CONNECTION = @@ -492,6 +500,8 @@ namespace ignite c_DocumentDbConnection = FindClass(env, C_DOCUMENTDB_CONNECTION); //m_DocumentDbConnectionInit = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_PROPERTIES_INIT); + m_DocumentDbConnectionGetSshLocalPort = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT); + m_DocumentDbConnectionIsSshTunnelActive = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_IS_SSH_TUNNEL_ACTIVE); c_DriverManager = FindClass(env, C_DRIVERMANAGER); m_DriverManagerGetConnection = FindMethod(env, c_DriverManager, M_DRIVERMANAGER_GET_CONNECTION); @@ -824,6 +834,55 @@ namespace ignite return true; } + // note to self: result is stored in bool poiner isActive, this is to be consistent with other functions that + // use CallBooleanMethod. -AL- + bool JniContext::DocumentDbIsSshTunnelActive( + const SharedPointer< GlobalJObject >& connection, + bool& isActive, + JniErrorInfo* errInfo) { + // to do implement -AL- + if (!connection.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "Connection object must be set."; + return false; + } + JNIEnv* env = Attach(); + jboolean res = env->CallBooleanMethod( + jvm->GetMembers().c_DocumentDbConnection, + jvm->GetMembers().m_DocumentDbConnectionIsSshTunnelActive); + ExceptionCheck(env, errInfo); + if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + isActive = res != JNI_TRUE; + } + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + // return result; + } + + int32_t JniContext::DocumentDbGetSshLocalPort( + const SharedPointer< GlobalJObject >& connection, + JniErrorInfo* errInfo) { + if (!connection.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "Connection object must be set."; + return false; + } + JNIEnv* env = Attach(); + int32_t result = env->CallIntMethod( + jvm->GetMembers().c_DocumentDbConnection, + jvm->GetMembers().m_DocumentDbConnectionGetSshLocalPort); + //jobject result = env->CallObjectMethod( + // jvm->GetMembers().c_DocumentDbConnection, + // jvm->GetMembers().m_DocumentDbConnectionGetSshLocalPort); + ExceptionCheck(env, errInfo); + //if (!result) { + // // unable to return object + // return 0; + //} else if (result.isPresent()) { + // return result.get().getInt(); + //} + return result; + } + void JniContext::ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo) { if (!connection.Get()) { errInfo->code = IGNITE_JNI_ERR_GENERIC; From bfb2b578d8e8a55005235afba25ad81be509ccf5 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 2 Feb 2022 14:42:20 -0800 Subject: [PATCH 123/165] [AD-521] debug getSshLocalPort * change function type signature from optional to int * refactor - remove comments --- src/odbc/src/jni/java.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index dc562f593..6da400326 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -274,12 +274,8 @@ namespace ignite false); const char* const C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; - // todo code draft -AL-. After constants all defined (define - // constants here), work on the JNI wrappers with Bruce JniMethod const M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT = - JniMethod("getSshLocalPort", "()Ljava/util/Optional;", false); -// JniMethod("getSshLocalPort", "()Ljava/util/Optional;", false); - // todo add call for isSshTunnelActive + JniMethod("getSshLocalPort", "()I;", false); JniMethod const M_DOCUMENTDB_CONNECTION_IS_SSH_TUNNEL_ACTIVE = JniMethod("isSshTunnelActive", "()B", false); From 58b11caf26fe1b02a65e8115cb0fde558f03e6bf Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 2 Feb 2022 18:06:18 -0800 Subject: [PATCH 124/165] [AD-521] change return value in getSshLocalPort from boolean to a 0 * try to fix access memory issue in TestDriverManagerGetConnection --- src/odbc-test/src/java_test.cpp | 3 ++- src/odbc/src/jni/java.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index 36ffacdcd..aac4449cc 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -158,7 +158,8 @@ BOOST_AUTO_TEST_CASE(TestDriverManagerGetConnection) BOOST_REQUIRE(connection.Get()); _ctx.Get()->ConnectionClose(connection, &errInfo); - connection = SharedPointer< GlobalJObject >(nullptr); + //connection = SharedPointer< GlobalJObject >(nullptr); + connection = nullptr; // attempt to fix read error -AL- } BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 6da400326..3e759e962 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -836,7 +836,6 @@ namespace ignite const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo* errInfo) { - // to do implement -AL- if (!connection.Get()) { errInfo->code = IGNITE_JNI_ERR_GENERIC; errInfo->errMsg = "Connection object must be set."; @@ -860,7 +859,8 @@ namespace ignite if (!connection.Get()) { errInfo->code = IGNITE_JNI_ERR_GENERIC; errInfo->errMsg = "Connection object must be set."; - return false; + return 0; + // TODO double check with Bruce: should I just return 0 here? } JNIEnv* env = Attach(); int32_t result = env->CallIntMethod( From 136d98399f83c6a0a16a2a09076486200584fcc6 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 3 Feb 2022 14:31:23 -0800 Subject: [PATCH 125/165] [AD-522] resolve build errors after merge * fix bug for schema name not correctly loaded on the config window * removed unnecessary headers --- .../odbc/system/ui/dsn_configuration_window.h | 4 ---- .../src/system/ui/dsn_configuration_window.cpp | 2 +- src/odbc/src/config/configuration.cpp | 1 + .../src/config/connection_string_parser.cpp | 18 ++++++++---------- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h index 0e554314b..787e34a1b 100644 --- a/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h +++ b/src/odbc/include/ignite/odbc/system/ui/dsn_configuration_window.h @@ -20,10 +20,6 @@ #include "ignite/odbc/config/configuration.h" #include "ignite/odbc/system/ui/custom_window.h" -// TODO: Removed these from configuration.h since no longer used. Moved here since they are still referenced. Remove when no longer needed. -#include "ignite/odbc/nested_tx_mode.h" -#include "ignite/odbc/protocol_version.h" -#include "ignite/odbc/ssl_mode.h" namespace ignite { diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 4092e36b4..89d595b2f 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -384,7 +384,7 @@ namespace ignite rowPos += INTERVAL + ROW_HEIGHT; - val = config.GetDatabase().c_str(); + val = config.GetSchemaName().c_str(); schemaLabel = CreateLabel(labelPosX, rowPos, LABEL_WIDTH, ROW_HEIGHT, "Schema Name:", ChildId::SCHEMA_LABEL); schemaEdit = CreateEdit(editPosX, rowPos, editSizeX, ROW_HEIGHT, val, ChildId::SCHEMA_EDIT); diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 041636851..2ee47fd9b 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -52,6 +52,7 @@ namespace ignite const bool Configuration::DefaultValue::refreshSchema = false; // Internal SSH Tunnel options + const bool Configuration::DefaultValue::sshEnable = false; const std::string Configuration::DefaultValue::sshUser = ""; const std::string Configuration::DefaultValue::sshHost = ""; const std::string Configuration::DefaultValue::sshPrivateKeyFile = ""; diff --git a/src/odbc/src/config/connection_string_parser.cpp b/src/odbc/src/config/connection_string_parser.cpp index d3b5ef831..7c1df403d 100644 --- a/src/odbc/src/config/connection_string_parser.cpp +++ b/src/odbc/src/config/connection_string_parser.cpp @@ -338,23 +338,21 @@ namespace ignite } else if (lKey == Key::sshEnable) { - BoolParseResult::Type res = StringToBool(value); - if (res == BoolParseResult::AI_UNRECOGNIZED) { - if (diag) { - diag->AddStatusRecord( - SqlState::S01S02_OPTION_VALUE_CHANGED, - MakeErrorMessage("Unrecognized bool value. " - "Using default value.", - key, value)); + if (res == BoolParseResult::Type::AI_UNRECOGNIZED) + { + if (diag) + { + diag->AddStatusRecord(SqlState::S01S02_OPTION_VALUE_CHANGED, + MakeErrorMessage("Unrecognized bool value. Using default value.", key, value)); } return; } - cfg.SetSshEnable(res == BoolParseResult::AI_TRUE); - } + cfg.SetSshEnable(res == BoolParseResult::Type::AI_TRUE); + } else if (lKey == Key::sshUser) { cfg.SetSshUser(value); From e59c35fdf6849d2316c8908cc2359abdc519455a Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Thu, 3 Feb 2022 15:08:37 -0800 Subject: [PATCH 126/165] [AD-427] Added ResultSet.next and ResultSet.GetString() --- README.md | 11 +++++++ src/odbc-test/src/java_test.cpp | 41 ++++++++++++++++++++++-- src/odbc/include/ignite/odbc/jni/java.h | 13 ++++++-- src/odbc/src/jni/java.cpp | 42 ++++++++++++++++++------- 4 files changed, 90 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 7db369e0d..3083793b9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,17 @@ ## Development Environment +### Environment Variables for Testing Accounts/Secrets + +The enable the test environment to run the tests against a live DocumentDB system, +set the follwoing environment variables + +1. `DOC_DB_HOST=` (e.g.: `docdb-host.cluster-cjf6q8nxfefi.us-east-2.docdb.amazonaws.com`) +2. `DOC_DB_PRIV_KEY_FILE=` (e.g.: `~/.ssh/ssh_host.pem`) +3. `DOC_DB_PASSWORD=` +4. `DOC_DB_USER=` (e.g., ec2-user@3.139.97.218) +5. `DOC_DB_USER_NAME=` + ### Windows 1. Microsoft Visual Studio (Community 2019 Verified) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index 36ffacdcd..09a079acf 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -92,7 +92,7 @@ struct JavaTestSuiteFixture: odbc::OdbcTestSuite SharedPointer< JniContext > ctx(JniContext::Create( &opts[0], static_cast< int >(opts.size()), JniHandlers())); - BOOST_CHECK(ctx.Get()); + BOOST_CHECK(ctx.Get() != nullptr); return ctx; } @@ -206,15 +206,50 @@ BOOST_AUTO_TEST_CASE(TestDatabaseMetaDataGetTables) { } BOOST_REQUIRE(databaseMetaData.Get()); + std::string catalog; + std::string schemaPattern; + std::string tableNamePattern; + std::vector< std::string > types({"TABLE"}); // Need to specify this to get result. SharedPointer< GlobalJObject > resultSet; - if (!_ctx.Get()->DatabaseMetaDataGetTables(databaseMetaData, resultSet, - &errInfo)) { + if (!_ctx.Get()->DatabaseMetaDataGetTables(databaseMetaData, catalog, + schemaPattern, tableNamePattern, + types, resultSet, &errInfo)) { std::string errMsg = errInfo.errMsg; _ctx.Get()->ConnectionClose(connection, &errInfo); BOOST_FAIL(errMsg); } BOOST_REQUIRE(resultSet.Get()); + bool hasNext; + if (!_ctx.Get()->ResultSetNext(resultSet, hasNext, &errInfo)) { + std::string errMsg = errInfo.errMsg; + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(hasNext); + + bool wasNull; + std::string value; + // TABLE_SCHEM (i.e., database) + if (!_ctx.Get()->ResultSetGetString(resultSet, 2, value, wasNull, + &errInfo)) { + std::string errMsg = errInfo.errMsg; + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(!wasNull); + BOOST_REQUIRE(value == "test"); + + // TABLE_NAME + if (!_ctx.Get()->ResultSetGetString(resultSet, 3, value, wasNull, + &errInfo)) { + std::string errMsg = errInfo.errMsg; + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(!wasNull); + BOOST_REQUIRE(value.size() > 0); + _ctx.Get()->ConnectionClose(connection, &errInfo); connection = nullptr; } diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index d85921ca0..eb23c407b 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -227,6 +227,8 @@ namespace ignite { jmethodID m_Throwable_getMessage; jmethodID m_Throwable_printStackTrace; + jclass c_String; + jclass c_PlatformUtils; jmethodID m_PlatformUtils_getFullStackTrace; @@ -445,11 +447,18 @@ namespace ignite { void ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo); bool ConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject>& databaseMetaData, JniErrorInfo* errInfo); - bool DatabaseMetaDataGetTables(const SharedPointer< GlobalJObject >& databaseMetaData, SharedPointer< GlobalJObject >& resultSet, JniErrorInfo* errInfo); + bool DatabaseMetaDataGetTables( + const SharedPointer< GlobalJObject >& databaseMetaData, + const std::string& catalog, + const std::string& schemaPattern, + const std::string& tableNamePattern, + const std::vector< std::string >& types, + SharedPointer< GlobalJObject >& resultSet, + JniErrorInfo* errInfo); bool ResultSetNext(const SharedPointer< GlobalJObject >& resultSet, bool& hasNext, JniErrorInfo* errInfo); - bool ResultSetGetString(const jobject resultSet, int columnIndex, std::string& value, bool& wasNull, JniErrorInfo* errInfo); + bool ResultSetGetString(const SharedPointer< GlobalJObject >& resultSet, int columnIndex, std::string& value, bool& wasNull, JniErrorInfo* errInfo); bool ResultSetGetString(const jobject resultSet, const std::string& columnName, std::string& value, bool& wasNull, JniErrorInfo* errInfo); bool ResultSetGetInteger(const jobject resultSet, int columnIndex, int& value, bool& wasNull, JniErrorInfo* errInfo); bool ResultSetGetInteger(const jobject resultSet, const std::string& columnName, int& value, bool& wasNull, JniErrorInfo* errInfo); diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index ee5077582..9bb5a8b51 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -236,6 +236,8 @@ namespace ignite const char* const C_CLASS = "java/lang/Class"; JniMethod const M_CLASS_GET_NAME = JniMethod("getName", "()Ljava/lang/String;", false); + const char* const C_STRING = "java/lang/String"; + const char* const C_DOCUMENTDB_CONNECTION_PROPERTIES = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; JniMethod const M_DOCUMENTDB_CONNECTION_PROPERTIES_GET_PROPERTIES_FROM_CONNECTION_STRING = @@ -430,6 +432,8 @@ namespace ignite m_Throwable_getMessage = FindMethod(env, c_Throwable, M_THROWABLE_GET_MESSAGE); m_Throwable_printStackTrace = FindMethod(env, c_Throwable, M_THROWABLE_PRINT_STACK_TRACE); + c_String = FindClass(env, C_STRING); + // TODO: Provide "getFullStackTrace" in DocumentDB //m_PlatformUtils_getFullStackTrace = FindMethod(env, c_PlatformUtils, M_PLATFORM_UTILS_GET_FULL_STACK_TRACE); } @@ -864,6 +868,10 @@ namespace ignite bool JniContext::DatabaseMetaDataGetTables( const SharedPointer< GlobalJObject >& databaseMetaData, + const std::string& catalog, + const std::string& schemaPattern, + const std::string& tableNamePattern, + const std::vector< std::string >& types, SharedPointer< GlobalJObject >& resultSet, JniErrorInfo* errInfo) { if (!databaseMetaData.Get()) { @@ -873,13 +881,23 @@ namespace ignite } JNIEnv* env = Attach(); + jstring jCatalog = env->NewStringUTF(catalog.c_str()); + jstring jSchemaPattern = env->NewStringUTF(schemaPattern.c_str()); + jstring jTableNamePattern = env->NewStringUTF(tableNamePattern.c_str()); + jobjectArray jTypes = env->NewObjectArray( + static_cast< jsize >(types.size()), jvm->GetJavaMembers().c_String, nullptr); + for (int i = 0; i < types.size(); i++) { + env->SetObjectArrayElement( + jTypes, i, env->NewStringUTF(types[i].c_str())); + } + jobject result = env->CallObjectMethod( databaseMetaData.Get()->GetRef(), jvm->GetMembers().m_DatabaseMetaDataGetTables, - /* catalog */ nullptr, - /* schemaPattern */ nullptr, - /* tableNamePattern */ nullptr, - /* types[]*/ nullptr); + jCatalog, + jSchemaPattern, + jTableNamePattern, + jTypes); ExceptionCheck(env, errInfo); if (!result || errInfo->code != IGNITE_JNI_ERR_SUCCESS) { @@ -907,17 +925,16 @@ namespace ignite jvm->GetMembers().m_ResultSetNext); ExceptionCheck(env, errInfo); if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { - hasNext = res != JNI_TRUE; + hasNext = res != JNI_FALSE; } return errInfo->code == IGNITE_JNI_ERR_SUCCESS; } - bool JniContext::ResultSetGetString(const jobject resultSet, - int columnIndex, - std::string& value, - bool& wasNull, - JniErrorInfo* errInfo) { - if (!resultSet) { + bool JniContext::ResultSetGetString( + const SharedPointer< GlobalJObject >& resultSet, + int columnIndex, std::string& value, bool& wasNull, + JniErrorInfo* errInfo) { + if (!resultSet.Get()) { errInfo->code = IGNITE_JNI_ERR_GENERIC; errInfo->errMsg = "ResultSet object must be set."; return false; @@ -925,7 +942,8 @@ namespace ignite JNIEnv* env = Attach(); jobject result = env->CallObjectMethod( - resultSet, jvm->GetMembers().m_ResultSetGetStringByIndex, + resultSet.Get()->GetRef(), + jvm->GetMembers().m_ResultSetGetStringByIndex, columnIndex); ExceptionCheck(env, errInfo); From e8288bfaf15aafeb4a48b7701da9f8ffcc5ac711 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 3 Feb 2022 15:12:37 -0800 Subject: [PATCH 127/165] [AD-522] address code review comments * change to enum class type for read_preference.h and scan_method.h * change the way enum class objects are read * add static cast to enum types so SetSelection function can work with it * refactor - removed unnecessary comments * refactor - changes code doc in connection_string_parser.h --- .../ignite/odbc/config/connection_string_parser.h | 4 ++-- src/odbc/include/ignite/odbc/read_preference.h | 2 +- src/odbc/include/ignite/odbc/scan_method.h | 2 +- .../win/src/system/ui/dsn_configuration_window.cpp | 14 +++++++------- src/odbc/src/config/configuration.cpp | 2 -- 5 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/odbc/include/ignite/odbc/config/connection_string_parser.h b/src/odbc/include/ignite/odbc/config/connection_string_parser.h index a7702f185..4ee17f403 100644 --- a/src/odbc/include/ignite/odbc/config/connection_string_parser.h +++ b/src/odbc/include/ignite/odbc/config/connection_string_parser.h @@ -83,10 +83,10 @@ namespace ignite /** Connection attribute keyword for tlsCaFile attribute. */ static const std::string tlsCaFile; - /** Connection attribute keyword for ssh enable attribute. */ + /** Connection attribute keyword for sshEnable attribute. */ static const std::string sshEnable; - /** Connection attribute keyword for password attribute. */ + /** Connection attribute keyword for sshUser attribute. */ static const std::string sshUser; /** Connection attribute keyword for sshHost attribute. */ diff --git a/src/odbc/include/ignite/odbc/read_preference.h b/src/odbc/include/ignite/odbc/read_preference.h index a05916eab..8b71b8f4f 100644 --- a/src/odbc/include/ignite/odbc/read_preference.h +++ b/src/odbc/include/ignite/odbc/read_preference.h @@ -26,7 +26,7 @@ namespace ignite /** Read Preference enum. */ struct ReadPreference { - enum Type + enum class Type { PRIMARY, PRIMARY_PREFERRED, diff --git a/src/odbc/include/ignite/odbc/scan_method.h b/src/odbc/include/ignite/odbc/scan_method.h index 70b24b835..a7c73c52e 100644 --- a/src/odbc/include/ignite/odbc/scan_method.h +++ b/src/odbc/include/ignite/odbc/scan_method.h @@ -26,7 +26,7 @@ namespace ignite /** Scan method enum. */ struct ScanMethod { - enum Type + enum class Type { RANDOM, ID_FORWARD, diff --git a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp index 89d595b2f..55627a66d 100644 --- a/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp +++ b/src/odbc/os/win/src/system/ui/dsn_configuration_window.cpp @@ -369,7 +369,7 @@ namespace ignite scanMethodComboBox->AddString("ID Reverse"); scanMethodComboBox->AddString("All"); - scanMethodComboBox->SetSelection(scanMethod); // set default + scanMethodComboBox->SetSelection(static_cast(scanMethod)); // set default rowPos += INTERVAL + ROW_HEIGHT; @@ -402,8 +402,8 @@ namespace ignite std::string scanMethodStr; scanMethodComboBox->GetText(scanMethodStr); if (ScanMethod::FromString(scanMethodStr, - ScanMethod::UNKNOWN) - == ScanMethod::ALL) { + ScanMethod::Type::UNKNOWN) + == ScanMethod::Type::ALL) { scanLimitEdit->SetEnabled(false); } else { scanLimitEdit->SetEnabled(true); @@ -447,7 +447,7 @@ namespace ignite readPreferenceComboBox->AddString("Secondary Preferred"); readPreferenceComboBox->AddString("Nearest"); - readPreferenceComboBox->SetSelection(readPreference); // set default + readPreferenceComboBox->SetSelection(static_cast(readPreference)); // set default rowPos += INTERVAL + ROW_HEIGHT; @@ -613,8 +613,8 @@ namespace ignite std::string scanMethodStr; scanMethodComboBox->GetText(scanMethodStr); if (ScanMethod::FromString( - scanMethodStr, ScanMethod::UNKNOWN) - == ScanMethod::ALL) + scanMethodStr, ScanMethod::Type::UNKNOWN) + == ScanMethod::Type::ALL) { scanLimitEdit->SetEnabled(false); } @@ -783,7 +783,7 @@ namespace ignite LOG_MSG("Refresh schema: " << (refreshSchema ? "true" : "false")); ScanMethod::Type scanMethod = - ScanMethod::FromString(scanMethodStr, ScanMethod::UNKNOWN); + ScanMethod::FromString(scanMethodStr, ScanMethod::Type::UNKNOWN); cfg.SetScanMethod(scanMethod); cfg.SetSchemaName(schemaStr); diff --git a/src/odbc/src/config/configuration.cpp b/src/odbc/src/config/configuration.cpp index 2ee47fd9b..37275eb9c 100644 --- a/src/odbc/src/config/configuration.cpp +++ b/src/odbc/src/config/configuration.cpp @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -// configures for what is defined in .h .h has a lot of setable values, replaces with DocumentDB properties. #include #include #include @@ -33,7 +32,6 @@ namespace ignite // Connection Settings const std::string Configuration::DefaultValue::dsn = "DocumentDB DSN"; const std::string Configuration::DefaultValue::driver = "Amazon DocumentDB ODBC Driver"; - // driver does not need to be added in config window since it is chosen at the Data Source Administrator const std::string Configuration::DefaultValue::database = ""; const std::string Configuration::DefaultValue::hostname = ""; const uint16_t Configuration::DefaultValue::port = 27017; From 3d9c31031f3d7cf9f88276cdfbdce07fbb2f1262 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 3 Feb 2022 16:58:37 -0800 Subject: [PATCH 128/165] [AD-521] implement tests for JNI wrapper code * test for TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive is not yet active, need to be enabled when we can get external SSH tunnel working. * bug fix: re-implemented DocumentDbConnectionGetSshLocalPort and DocumentDbConnectionIsSshTunnelActive. connection.Get()->GetRef() is passed as first parameter because jobject is required for CallIntMethod and CallBooleanMethod. * better JNI wrapper code is needed in the future so warnings/errors pop up when we pass jobject instead of jclass to the methods. --- src/odbc-test/src/java_test.cpp | 97 +++++++++++++++++++++++++ src/odbc/include/ignite/odbc/jni/java.h | 6 +- src/odbc/src/jni/java.cpp | 35 ++++----- 3 files changed, 113 insertions(+), 25 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index aac4449cc..72cba46b5 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -187,6 +187,103 @@ BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { connection = nullptr; } +BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPort) { + PrepareContext(); + + // get Driver manager connection + JniErrorInfo errInfo; + SharedPointer< GlobalJObject > connection; + bool success = _ctx.Get()->DriverManagerGetConnection( + _jdbcConnectionString.c_str(), connection, &errInfo); + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(connection.Get()); + + // see if ssh tunnel is active + bool isActive; + success = _ctx.Get()->DocumentDbConnectionIsSshTunnelActive(connection, isActive, &errInfo); + // if tunnel is not shown as active, or operation not successful, BOOST FAIL + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errInfo.errMsg); + } + if (!isActive) { + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL("isActive is not true"); + } + + // ssh tunnel confirmed to be active, get ssh tunnel local port + int32_t port; + success = _ctx.Get()->DocumentDbConnectionGetSshLocalPort(connection, port, &errInfo); + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errMsg); + } + + // if connection successful, port should be a positive number + if (!(port > 0)) { + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL("port is not a positive number"); + } + + // close the connection after the test + _ctx.Get()->ConnectionClose(connection, &errInfo); + connection = nullptr; +} + +// TODO Enable when we can get external SSH tunnel working +BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, * disabled()) { +//BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive) { + // test when SSH tunnel is not active, the ssh tunnel port should be 0 + // TODO do things so SSH tunnel is not active, but connection is open + PrepareContext(); + + // get Driver manager connection + JniErrorInfo errInfo; + SharedPointer< GlobalJObject > connection; + bool success = _ctx.Get()->DriverManagerGetConnection( + _jdbcConnectionString.c_str(), connection, &errInfo); + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(connection.Get()); + + // check if ssh tunnel is not active + bool isActive; + success = _ctx.Get()->DocumentDbConnectionIsSshTunnelActive(connection, isActive, &errInfo); + // if SSH tunnel is active, or operation not successful, BOOST FAIL + if (isActive || !success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errInfo.errMsg); + } + + if (isActive) { + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL("isActive is not false"); + } + + // ssh tunnel confirmed to be not active, get ssh tunnel local port + int32_t port; + success = _ctx.Get()->DocumentDbConnectionGetSshLocalPort(connection, port, &errInfo); + if (errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errMsg); + } + + // if SSH tunnel not active, ssh local port number should be 0 + if (port != 0) { + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL("port is not equal to 0"); + } + + // close the connection after the test + _ctx.Get()->ConnectionClose(connection, &errInfo); + connection = nullptr; +} + BOOST_AUTO_TEST_CASE(TestDatabaseMetaDataGetTables) { PrepareContext(); diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index c7f49719b..b2acfeebd 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -447,8 +447,8 @@ namespace ignite { void ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo); bool ConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject>& databaseMetaData, JniErrorInfo* errInfo); - bool DocumentDbIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo* errInfo); - int32_t DocumentDbGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo); + bool DocumentDbConnectionIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo* errInfo); + bool DocumentDbConnectionGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, int32_t& result, JniErrorInfo* errInfo); bool DatabaseMetaDataGetTables(const SharedPointer< GlobalJObject >& databaseMetaData, SharedPointer< GlobalJObject >& resultSet, JniErrorInfo* errInfo); @@ -694,5 +694,5 @@ namespace ignite { } // namespace jni } // namespace odbc } // namespace ignite - #endif //_IGNITE_ODBC_JNI_JAVA + diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 3e759e962..815cf91ad 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -273,11 +273,11 @@ namespace ignite "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Ljava/sql/ResultSet;", false); - const char* const C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnectionProperties"; + const char* const C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnection"; JniMethod const M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT = - JniMethod("getSshLocalPort", "()I;", false); + JniMethod("getSshLocalPort", "()I", false); JniMethod const M_DOCUMENTDB_CONNECTION_IS_SSH_TUNNEL_ACTIVE = - JniMethod("isSshTunnelActive", "()B", false); + JniMethod("isSshTunnelActive", "()Z", false); const char* const C_DRIVERMANAGER = "java/sql/DriverManager"; JniMethod const M_DRIVERMANAGER_GET_CONNECTION = @@ -832,7 +832,7 @@ namespace ignite // note to self: result is stored in bool poiner isActive, this is to be consistent with other functions that // use CallBooleanMethod. -AL- - bool JniContext::DocumentDbIsSshTunnelActive( + bool JniContext::DocumentDbConnectionIsSshTunnelActive( const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo* errInfo) { @@ -843,40 +843,31 @@ namespace ignite } JNIEnv* env = Attach(); jboolean res = env->CallBooleanMethod( - jvm->GetMembers().c_DocumentDbConnection, + connection.Get()->GetRef(), jvm->GetMembers().m_DocumentDbConnectionIsSshTunnelActive); ExceptionCheck(env, errInfo); if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { - isActive = res != JNI_TRUE; + isActive = res != JNI_FALSE; } return errInfo->code == IGNITE_JNI_ERR_SUCCESS; - // return result; } - int32_t JniContext::DocumentDbGetSshLocalPort( + // use a reference variable to return a value, return a boolean to indicate whether it is successful or not -AL- + bool JniContext::DocumentDbConnectionGetSshLocalPort( const SharedPointer< GlobalJObject >& connection, + int32_t& result, JniErrorInfo* errInfo) { if (!connection.Get()) { errInfo->code = IGNITE_JNI_ERR_GENERIC; errInfo->errMsg = "Connection object must be set."; - return 0; - // TODO double check with Bruce: should I just return 0 here? + return false; } JNIEnv* env = Attach(); - int32_t result = env->CallIntMethod( - jvm->GetMembers().c_DocumentDbConnection, + result = env->CallIntMethod( + connection.Get()->GetRef(), jvm->GetMembers().m_DocumentDbConnectionGetSshLocalPort); - //jobject result = env->CallObjectMethod( - // jvm->GetMembers().c_DocumentDbConnection, - // jvm->GetMembers().m_DocumentDbConnectionGetSshLocalPort); ExceptionCheck(env, errInfo); - //if (!result) { - // // unable to return object - // return 0; - //} else if (result.isPresent()) { - // return result.get().getInt(); - //} - return result; + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; } void JniContext::ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo) { From 3f8c3cbe27ab412714ea677394180c88a8a17a77 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Fri, 4 Feb 2022 09:37:06 -0800 Subject: [PATCH 129/165] [AD-521] refactor - remove comments and commented out code --- src/odbc-test/src/java_test.cpp | 3 +-- src/odbc/src/jni/java.cpp | 3 --- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index 730e62a46..e9d3c6a88 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -158,8 +158,7 @@ BOOST_AUTO_TEST_CASE(TestDriverManagerGetConnection) BOOST_REQUIRE(connection.Get()); _ctx.Get()->ConnectionClose(connection, &errInfo); - //connection = SharedPointer< GlobalJObject >(nullptr); - connection = nullptr; // attempt to fix read error -AL- + connection = nullptr; } BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 17ad62270..be3eb2255 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -834,8 +834,6 @@ namespace ignite return true; } - // note to self: result is stored in bool poiner isActive, this is to be consistent with other functions that - // use CallBooleanMethod. -AL- bool JniContext::DocumentDbConnectionIsSshTunnelActive( const SharedPointer< GlobalJObject >& connection, bool& isActive, @@ -856,7 +854,6 @@ namespace ignite return errInfo->code == IGNITE_JNI_ERR_SUCCESS; } - // use a reference variable to return a value, return a boolean to indicate whether it is successful or not -AL- bool JniContext::DocumentDbConnectionGetSshLocalPort( const SharedPointer< GlobalJObject >& connection, int32_t& result, From 5901f5de2da54165fbba1ee642d1df4d0bee3df2 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 7 Feb 2022 15:22:01 -0800 Subject: [PATCH 130/165] [AD-589] implement JNI method call for GetDatabaseMetadata * define the method constant for DocumentDbConnection.getDatabaseMetadata() * create JNI wrapper function for DocumentDbConnection.getMetaData --- src/odbc/include/ignite/odbc/jni/java.h | 2 ++ src/odbc/src/jni/java.cpp | 29 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index 53e6e0451..f2559e4bc 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -260,6 +260,7 @@ namespace ignite { jclass c_DocumentDbConnection; jmethodID m_DocumentDbConnectionGetSshLocalPort; jmethodID m_DocumentDbConnectionIsSshTunnelActive; + jmethodID m_DocumentDbConnectionGetDatabaseMetadata; jmethodID m_DocumentDbConnectionInit; jmethodID m_DocumentDbClose; @@ -451,6 +452,7 @@ namespace ignite { bool DocumentDbConnectionIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo* errInfo); bool DocumentDbConnectionGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, int32_t& result, JniErrorInfo* errInfo); + bool DocumentDbConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo* errInfo); bool DatabaseMetaDataGetTables(const SharedPointer< GlobalJObject >& databaseMetaData, SharedPointer< GlobalJObject >& resultSet, JniErrorInfo* errInfo); bool DatabaseMetaDataGetTables( diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index be3eb2255..5a037cd46 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -280,6 +280,8 @@ namespace ignite JniMethod("getSshLocalPort", "()I", false); JniMethod const M_DOCUMENTDB_CONNECTION_IS_SSH_TUNNEL_ACTIVE = JniMethod("isSshTunnelActive", "()Z", false); + JniMethod const M_DOCUMENTDB_CONNECTION_GET_DATABASE_METADATA = + JniMethod("getDatabaseMetadata", "()Lsoftware/amazon/documentdb/jdbc/metadata/DocumentDbDatabaseSchemaMetadata;", false); // TODO -AL- not done const char* const C_DRIVERMANAGER = "java/sql/DriverManager"; JniMethod const M_DRIVERMANAGER_GET_CONNECTION = @@ -502,6 +504,7 @@ namespace ignite //m_DocumentDbConnectionInit = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_PROPERTIES_INIT); m_DocumentDbConnectionGetSshLocalPort = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT); m_DocumentDbConnectionIsSshTunnelActive = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_IS_SSH_TUNNEL_ACTIVE); + m_DocumentDbConnectionGetDatabaseMetadata = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_GET_DATABASE_METADATA); c_DriverManager = FindClass(env, C_DRIVERMANAGER); m_DriverManagerGetConnection = FindMethod(env, c_DriverManager, M_DRIVERMANAGER_GET_CONNECTION); @@ -871,6 +874,32 @@ namespace ignite return errInfo->code == IGNITE_JNI_ERR_SUCCESS; } + bool JniContext::DocumentDbConnectionGetMetaData( + const SharedPointer< GlobalJObject >& connection, + SharedPointer< GlobalJObject >& metaData, + JniErrorInfo* errInfo) { + if (!connection.Get()) { + errInfo->code = IGNITE_JNI_ERR_GENERIC; + errInfo->errMsg = "Connection object must be set."; + return false; + } + JNIEnv* env = Attach(); + jobject result = env->CallObjectMethod( + connection.Get()->GetRef(), + jvm->GetMembers().m_DocumentDbConnectionGetDatabaseMetadata); + ExceptionCheck(env, errInfo); + + if (!result || errInfo->code != IGNITE_JNI_ERR_SUCCESS) { + metaData = + SharedPointer< GlobalJObject >(nullptr); + return false; + } + + metaData = SharedPointer< GlobalJObject >( + new GlobalJObject(env, env->NewGlobalRef(result))); + return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + } + void JniContext::ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo* errInfo) { if (!connection.Get()) { errInfo->code = IGNITE_JNI_ERR_GENERIC; From 16906fcf8a258f946bab37b49619abd6c328a723 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Mon, 7 Feb 2022 15:27:15 -0800 Subject: [PATCH 131/165] [AD-589] implement unit test for DocumentDbConnection.getMetaData --- src/odbc-test/src/java_test.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index e9d3c6a88..fbacf30cf 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -283,6 +283,33 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, connection = nullptr; } +BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { + PrepareContext(); + + // get Driver manager connection + JniErrorInfo errInfo; + SharedPointer< GlobalJObject > connection; + bool success = _ctx.Get()->DriverManagerGetConnection( + _jdbcConnectionString.c_str(), connection, &errInfo); + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(connection.Get()); + + // get metadata + SharedPointer< GlobalJObject > databaseMetaData; + if (!_ctx.Get()->ConnectionGetMetaData(connection, databaseMetaData, + &errInfo)) { + std::string errMsg = errInfo.errMsg; + _ctx.Get()->ConnectionClose(connection, &errInfo); + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(databaseMetaData.Get()); + + _ctx.Get()->ConnectionClose(connection, &errInfo); + connection = nullptr; +} + BOOST_AUTO_TEST_CASE(TestDatabaseMetaDataGetTables) { PrepareContext(); From 63c0dacc228957a890cd87893cedbfa35c6e64aa Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 8 Feb 2022 14:52:05 -0800 Subject: [PATCH 132/165] [AD-521] add calls to AutoCloseConnection in unit tests * pass & errInfo instead of * errInfo in DocumentDbConnectionGetSshLocalPort and DocumentDbConnectionIsSshTunnelActive. --- src/odbc-test/src/java_test.cpp | 50 +++++++------------------ src/odbc/include/ignite/odbc/jni/java.h | 6 +-- src/odbc/src/jni/java.cpp | 24 ++++++------ 3 files changed, 29 insertions(+), 51 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index 9c7fc4525..c077835d7 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -206,51 +206,39 @@ BOOST_AUTO_TEST_CASE(TestDriverManagerGetConnection) connection = SharedPointer< GlobalJObject >(nullptr); } -// TODO change and add calls to AutoConnectionClose -AL- BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPort) { PrepareContext(); + BOOST_REQUIRE(_ctx.Get() != nullptr); // get Driver manager connection JniErrorInfo errInfo; SharedPointer< GlobalJObject > connection; - bool success = _ctx.Get()->DriverManagerGetConnection( - _jdbcConnectionString.c_str(), connection, &errInfo); + bool success = _ctx.Get()->DriverManagerGetConnection(_jdbcConnectionString.c_str(), connection, errInfo); if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { BOOST_FAIL(errInfo.errMsg); } BOOST_REQUIRE(connection.Get()); + AutoCloseConnection autoCloseConnection(_ctx, connection); // see if ssh tunnel is active bool isActive; - success = _ctx.Get()->DocumentDbConnectionIsSshTunnelActive(connection, isActive, &errInfo); + success = _ctx.Get()->DocumentDbConnectionIsSshTunnelActive(connection, isActive, errInfo); // if tunnel is not shown as active, or operation not successful, BOOST FAIL if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { - _ctx.Get()->ConnectionClose(connection, &errInfo); BOOST_FAIL(errInfo.errMsg); } - if (!isActive) { - _ctx.Get()->ConnectionClose(connection, &errInfo); - BOOST_FAIL("isActive is not true"); - } + BOOST_CHECK(isActive); // ssh tunnel confirmed to be active, get ssh tunnel local port int32_t port; - success = _ctx.Get()->DocumentDbConnectionGetSshLocalPort(connection, port, &errInfo); + success = _ctx.Get()->DocumentDbConnectionGetSshLocalPort(connection, port, errInfo); if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { std::string errMsg = errInfo.errMsg; - _ctx.Get()->ConnectionClose(connection, &errInfo); BOOST_FAIL(errMsg); } // if connection successful, port should be a positive number - if (!(port > 0)) { - _ctx.Get()->ConnectionClose(connection, &errInfo); - BOOST_FAIL("port is not a positive number"); - } - - // close the connection after the test - _ctx.Get()->ConnectionClose(connection, &errInfo); - connection = nullptr; + BOOST_CHECK(port > 0); } // TODO Enable when we can get external SSH tunnel working @@ -259,49 +247,39 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, // test when SSH tunnel is not active, the ssh tunnel port should be 0 // TODO do things so SSH tunnel is not active, but connection is open PrepareContext(); + BOOST_REQUIRE(_ctx.Get() != nullptr); // get Driver manager connection JniErrorInfo errInfo; SharedPointer< GlobalJObject > connection; bool success = _ctx.Get()->DriverManagerGetConnection( - _jdbcConnectionString.c_str(), connection, &errInfo); + _jdbcConnectionString.c_str(), connection, errInfo); if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { BOOST_FAIL(errInfo.errMsg); } BOOST_REQUIRE(connection.Get()); + AutoCloseConnection autoCloseConnection(_ctx, connection); // check if ssh tunnel is not active bool isActive; - success = _ctx.Get()->DocumentDbConnectionIsSshTunnelActive(connection, isActive, &errInfo); + success = _ctx.Get()->DocumentDbConnectionIsSshTunnelActive(connection, isActive, errInfo); // if SSH tunnel is active, or operation not successful, BOOST FAIL if (isActive || !success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { - _ctx.Get()->ConnectionClose(connection, &errInfo); BOOST_FAIL(errInfo.errMsg); } - if (isActive) { - _ctx.Get()->ConnectionClose(connection, &errInfo); - BOOST_FAIL("isActive is not false"); - } + BOOST_CHECK(!isActive); // ssh tunnel confirmed to be not active, get ssh tunnel local port int32_t port; - success = _ctx.Get()->DocumentDbConnectionGetSshLocalPort(connection, port, &errInfo); + success = _ctx.Get()->DocumentDbConnectionGetSshLocalPort(connection, port, errInfo); if (errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { std::string errMsg = errInfo.errMsg; - _ctx.Get()->ConnectionClose(connection, &errInfo); BOOST_FAIL(errMsg); } // if SSH tunnel not active, ssh local port number should be 0 - if (port != 0) { - _ctx.Get()->ConnectionClose(connection, &errInfo); - BOOST_FAIL("port is not equal to 0"); - } - - // close the connection after the test - _ctx.Get()->ConnectionClose(connection, &errInfo); - connection = nullptr; + BOOST_CHECK_EQUAL(port, 0); } BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index cf1e7661e..3e84515f0 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -446,13 +446,13 @@ namespace ignite { static void SetConsoleHandler(ConsoleWriteHandler consoleHandler); static int RemoveConsoleHandler(ConsoleWriteHandler consoleHandler); - bool DocumentDbConnectionIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo* errInfo); - bool DocumentDbConnectionGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, int32_t& result, JniErrorInfo* errInfo); - bool DriverManagerGetConnection(const char* connectionString, SharedPointer< GlobalJObject >& connection, JniErrorInfo& errInfo); void ConnectionClose(const SharedPointer< GlobalJObject >& connection, JniErrorInfo& errInfo); bool ConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject>& databaseMetaData, JniErrorInfo& errInfo); + bool DocumentDbConnectionIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo& errInfo); + bool DocumentDbConnectionGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, int32_t& result, JniErrorInfo& errInfo); + bool DatabaseMetaDataGetTables( const SharedPointer< GlobalJObject >& databaseMetaData, const std::string& catalog, diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index aab360578..e3561009f 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -832,39 +832,39 @@ namespace ignite bool JniContext::DocumentDbConnectionIsSshTunnelActive( const SharedPointer< GlobalJObject >& connection, bool& isActive, - JniErrorInfo* errInfo) { + JniErrorInfo& errInfo) { if (!connection.Get()) { - errInfo->code = IGNITE_JNI_ERR_GENERIC; - errInfo->errMsg = "Connection object must be set."; + errInfo.code = IGNITE_JNI_ERR_GENERIC; + errInfo.errMsg = "Connection object must be set."; return false; } JNIEnv* env = Attach(); jboolean res = env->CallBooleanMethod( connection.Get()->GetRef(), jvm->GetMembers().m_DocumentDbConnectionIsSshTunnelActive); - ExceptionCheck(env, errInfo); - if (errInfo->code == IGNITE_JNI_ERR_SUCCESS) { + ExceptionCheck(env, &errInfo); + if (errInfo.code == IGNITE_JNI_ERR_SUCCESS) { isActive = res != JNI_FALSE; } - return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + return errInfo.code == IGNITE_JNI_ERR_SUCCESS; } bool JniContext::DocumentDbConnectionGetSshLocalPort( const SharedPointer< GlobalJObject >& connection, int32_t& result, - JniErrorInfo* errInfo) { + JniErrorInfo& errInfo) { if (!connection.Get()) { - errInfo->code = IGNITE_JNI_ERR_GENERIC; - errInfo->errMsg = "Connection object must be set."; + errInfo.code = IGNITE_JNI_ERR_GENERIC; + errInfo.errMsg = "Connection object must be set."; return false; } JNIEnv* env = Attach(); result = env->CallIntMethod( connection.Get()->GetRef(), jvm->GetMembers().m_DocumentDbConnectionGetSshLocalPort); - ExceptionCheck(env, errInfo); - return errInfo->code == IGNITE_JNI_ERR_SUCCESS; - } + ExceptionCheck(env, &errInfo); + return errInfo.code == IGNITE_JNI_ERR_SUCCESS; + } bool JniContext::ConnectionGetMetaData( const SharedPointer< GlobalJObject >& connection, From a65e781be5f08dd273d15439670056818d18d687 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 8 Feb 2022 14:57:51 -0800 Subject: [PATCH 133/165] [AD-521] remove unnecessary comment --- src/odbc/src/jni/java.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index e3561009f..885c06350 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -828,7 +828,6 @@ namespace ignite ExceptionCheck(env, &errInfo); } - // -AL- todo changes are needed because & errInfo should be returned instead bool JniContext::DocumentDbConnectionIsSshTunnelActive( const SharedPointer< GlobalJObject >& connection, bool& isActive, From d0af445b59f99b2170af7096f132e315b91cb010 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 8 Feb 2022 14:59:15 -0800 Subject: [PATCH 134/165] [AD-589] fix merge issues * I missed this part of code when I was resolving the merge conflicts. Now they are corrected --- src/odbc/src/jni/java.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 7122bff28..308a3d85d 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -864,8 +864,8 @@ namespace ignite result = env->CallIntMethod( connection.Get()->GetRef(), jvm->GetMembers().m_DocumentDbConnectionGetSshLocalPort); - ExceptionCheck(env, errInfo); - return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + ExceptionCheck(env, &errInfo); + return errInfo.code == IGNITE_JNI_ERR_SUCCESS; } bool JniContext::DocumentDbConnectionGetMetaData( From 17ff0d2ce6aca7d0395c12bcbfbfbcc202adcdde Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 8 Feb 2022 15:30:54 -0800 Subject: [PATCH 135/165] [AD-589] update getMetaData JNI wrapper code to pass &errInfo * implement unit test for getMetaData --- src/odbc-test/src/java_test.cpp | 36 ++++++++++++++++--------- src/odbc/include/ignite/odbc/jni/java.h | 2 +- src/odbc/src/jni/java.cpp | 18 ++++++------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index 692f588d4..2e00675a5 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -282,10 +282,11 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, BOOST_CHECK_EQUAL(port, 0); } -BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { +BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { PrepareContext(); BOOST_REQUIRE(_ctx.Get() != nullptr); + // get Driver manager connection JniErrorInfo errInfo; SharedPointer< GlobalJObject > connection; bool success = _ctx.Get()->DriverManagerGetConnection( @@ -293,16 +294,17 @@ BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { BOOST_FAIL(errInfo.errMsg); } - BOOST_REQUIRE(connection.Get() != nullptr); + BOOST_REQUIRE(connection.Get()); AutoCloseConnection autoCloseConnection(_ctx, connection); + // get metadata SharedPointer< GlobalJObject > databaseMetaData; - if (!_ctx.Get()->ConnectionGetMetaData(connection, databaseMetaData, + if (!_ctx.Get()->DocumentDbConnectionGetMetaData( + connection, databaseMetaData, errInfo)) { - std::string errMsg = errInfo.errMsg; - BOOST_FAIL(errMsg); + BOOST_FAIL(errInfo.errMsg); } - BOOST_REQUIRE(databaseMetaData.Get() != nullptr); + BOOST_REQUIRE(databaseMetaData.Get()); } BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { @@ -319,17 +321,27 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { BOOST_REQUIRE(connection.Get()); // get metadata +BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { + PrepareContext(); + BOOST_REQUIRE(_ctx.Get() != nullptr); + + JniErrorInfo errInfo; + SharedPointer< GlobalJObject > connection; + bool success = _ctx.Get()->DriverManagerGetConnection( + _jdbcConnectionString.c_str(), connection, errInfo); + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(connection.Get() != nullptr); + AutoCloseConnection autoCloseConnection(_ctx, connection); + SharedPointer< GlobalJObject > databaseMetaData; if (!_ctx.Get()->ConnectionGetMetaData(connection, databaseMetaData, - &errInfo)) { + errInfo)) { std::string errMsg = errInfo.errMsg; - _ctx.Get()->ConnectionClose(connection, &errInfo); BOOST_FAIL(errMsg); } - BOOST_REQUIRE(databaseMetaData.Get()); - - _ctx.Get()->ConnectionClose(connection, &errInfo); - connection = nullptr; + BOOST_REQUIRE(databaseMetaData.Get() != nullptr); } BOOST_AUTO_TEST_CASE(TestDatabaseMetaDataGetTables) { diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index f33186928..3305fa45e 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -453,7 +453,7 @@ namespace ignite { bool DocumentDbConnectionIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo& errInfo); bool DocumentDbConnectionGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, int32_t& result, JniErrorInfo& errInfo); - bool DocumentDbConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo* errInfo); + bool DocumentDbConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo& errInfo); bool DatabaseMetaDataGetTables( const SharedPointer< GlobalJObject >& databaseMetaData, diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 308a3d85d..6fe88069f 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -284,7 +284,7 @@ namespace ignite JniMethod const M_DOCUMENTDB_CONNECTION_IS_SSH_TUNNEL_ACTIVE = JniMethod("isSshTunnelActive", "()Z", false); JniMethod const M_DOCUMENTDB_CONNECTION_GET_DATABASE_METADATA = - JniMethod("getDatabaseMetadata", "()Lsoftware/amazon/documentdb/jdbc/metadata/DocumentDbDatabaseSchemaMetadata;", false); // TODO -AL- not done + JniMethod("getDatabaseMetadata", "()Lsoftware/amazon/documentdb/jdbc/metadata/DocumentDbDatabaseSchemaMetadata;", false); const char* const C_DRIVERMANAGER = "java/sql/DriverManager"; JniMethod const M_DRIVERMANAGER_GET_CONNECTION = @@ -871,27 +871,27 @@ namespace ignite bool JniContext::DocumentDbConnectionGetMetaData( const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, - JniErrorInfo* errInfo) { + JniErrorInfo& errInfo) { if (!connection.Get()) { - errInfo->code = IGNITE_JNI_ERR_GENERIC; - errInfo->errMsg = "Connection object must be set."; + errInfo.code = IGNITE_JNI_ERR_GENERIC; + errInfo.errMsg = "Connection object must be set."; return false; } JNIEnv* env = Attach(); jobject result = env->CallObjectMethod( connection.Get()->GetRef(), jvm->GetMembers().m_DocumentDbConnectionGetDatabaseMetadata); - ExceptionCheck(env, errInfo); + ExceptionCheck(env, &errInfo); - if (!result || errInfo->code != IGNITE_JNI_ERR_SUCCESS) { - metaData = - SharedPointer< GlobalJObject >(nullptr); + if (!result || errInfo.code != IGNITE_JNI_ERR_SUCCESS) { + metaData = nullptr; return false; } metaData = SharedPointer< GlobalJObject >( new GlobalJObject(env, env->NewGlobalRef(result))); - return errInfo->code == IGNITE_JNI_ERR_SUCCESS; + return errInfo.code == IGNITE_JNI_ERR_SUCCESS; + } } bool JniContext::ConnectionGetMetaData( From 820ae7db615aaac3a0c905fcb2d855607d1029a9 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 8 Feb 2022 15:38:30 -0800 Subject: [PATCH 136/165] [AD-589] implement JNI wrapper for DocumentDbDatabaseSchemaMetadataGetSchemaName * implement Java class for * define constant for DocumentDbDatabaseSchemaMetadataGetSchemaName * add empty test function for TestDocumentDbDatabaseSchemaMetadataGetSchemaName --- src/odbc-test/src/java_test.cpp | 5 +++- src/odbc/include/ignite/odbc/jni/java.h | 5 ++++ src/odbc/src/jni/java.cpp | 38 +++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index 2e00675a5..630ec0166 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -307,7 +307,8 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { BOOST_REQUIRE(databaseMetaData.Get()); } -BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { +// steps: check not null, then check schema name -AL- draft comment +BOOST_AUTO_TEST_CASE(TestDocumentDbDatabaseSchemaMetadataGetSchemaName) { PrepareContext(); // get Driver manager connection @@ -321,6 +322,8 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { BOOST_REQUIRE(connection.Get()); // get metadata +} + BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { PrepareContext(); BOOST_REQUIRE(_ctx.Get() != nullptr); diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index 3305fa45e..b7d5af24b 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -264,6 +264,9 @@ namespace ignite { jmethodID m_DocumentDbConnectionInit; jmethodID m_DocumentDbClose; + jclass c_DocumentDbDatabaseSchemaMetadata; + jmethodID m_DocumentDbDatabaseSchemaMetadataGetSchemaName; + jclass c_DriverManager; jmethodID m_DriverManagerGetConnection; @@ -455,6 +458,8 @@ namespace ignite { bool DocumentDbConnectionGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, int32_t& result, JniErrorInfo& errInfo); bool DocumentDbConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo& errInfo); + bool DocumentDbDatabaseSchemaMetadataGetSchemaName(const SharedPointer< GlobalJObject >& databaseMetaData, std::string& value, bool& wasNull, JniErrorInfo& errInfo); + bool DatabaseMetaDataGetTables( const SharedPointer< GlobalJObject >& databaseMetaData, const std::string& catalog, diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 6fe88069f..182b11ff8 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -286,6 +286,12 @@ namespace ignite JniMethod const M_DOCUMENTDB_CONNECTION_GET_DATABASE_METADATA = JniMethod("getDatabaseMetadata", "()Lsoftware/amazon/documentdb/jdbc/metadata/DocumentDbDatabaseSchemaMetadata;", false); + const char* const C_DOCUMENTDB_DATABASE_SCHEMA_METADATA = + "software/amazon/documentdb/jdbc/metadata/DocumentDbDatabaseSchemaMetadata"; + JniMethod const M_DOCUMENTDB_DATABASE_SCHEMA_METADATA_GET_SCHEMA_NAME = + JniMethod("getSchemaName", "()Ljava/lang/String;", false); + + const char* const C_DRIVERMANAGER = "java/sql/DriverManager"; JniMethod const M_DRIVERMANAGER_GET_CONNECTION = JniMethod("getConnection", "(Ljava/lang/String;)Ljava/sql/Connection;", true); @@ -497,6 +503,9 @@ namespace ignite m_DocumentDbConnectionIsSshTunnelActive = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_IS_SSH_TUNNEL_ACTIVE); m_DocumentDbConnectionGetDatabaseMetadata = FindMethod(env, c_DocumentDbConnection, M_DOCUMENTDB_CONNECTION_GET_DATABASE_METADATA); + c_DocumentDbDatabaseSchemaMetadata = FindClass(env, C_DOCUMENTDB_DATABASE_SCHEMA_METADATA); + m_DocumentDbDatabaseSchemaMetadataGetSchemaName = FindMethod(env, c_DocumentDbDatabaseSchemaMetadata, M_DOCUMENTDB_DATABASE_SCHEMA_METADATA_GET_SCHEMA_NAME); + c_DriverManager = FindClass(env, C_DRIVERMANAGER); m_DriverManagerGetConnection = FindMethod(env, c_DriverManager, M_DRIVERMANAGER_GET_CONNECTION); @@ -892,6 +901,35 @@ namespace ignite new GlobalJObject(env, env->NewGlobalRef(result))); return errInfo.code == IGNITE_JNI_ERR_SUCCESS; } + + bool JniContext::DocumentDbDatabaseSchemaMetadataGetSchemaName( + const SharedPointer< GlobalJObject >& databaseMetaData, + std::string& value, bool& wasNull, JniErrorInfo& errInfo) + { + if (!databaseMetaData.Get()) { + errInfo.code = IGNITE_JNI_ERR_GENERIC; + errInfo.errMsg = "DatabaseMetaData object must be set."; + return false; + } + JNIEnv* env = Attach(); + jobject result = env->CallObjectMethod( + databaseMetaData.Get()->GetRef(), + jvm->GetMembers().m_DocumentDbDatabaseSchemaMetadataGetSchemaName); + ExceptionCheck(env, &errInfo); + + if (errInfo.code == IGNITE_JNI_ERR_SUCCESS) { + wasNull = !result; + if (result != nullptr) { + jboolean isCopy; + const char* utfChars = env->GetStringUTFChars( + (jstring)result, &isCopy); + value = std::string(utfChars); + env->ReleaseStringUTFChars((jstring)result, + utfChars); + } + } + + return errInfo.code == IGNITE_JNI_ERR_SUCCESS; } bool JniContext::ConnectionGetMetaData( From e14625e472dbcb9f54d65ae4ad12ef8422dea6ff Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Tue, 8 Feb 2022 15:59:02 -0800 Subject: [PATCH 137/165] [AD-589] implement unit test for DbDatabaseSchemaMetadataGetSchemaName --- src/odbc-test/src/java_test.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index 630ec0166..e79b3a876 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -307,21 +307,39 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { BOOST_REQUIRE(databaseMetaData.Get()); } -// steps: check not null, then check schema name -AL- draft comment BOOST_AUTO_TEST_CASE(TestDocumentDbDatabaseSchemaMetadataGetSchemaName) { PrepareContext(); + BOOST_REQUIRE(_ctx.Get() != nullptr); // get Driver manager connection JniErrorInfo errInfo; SharedPointer< GlobalJObject > connection; bool success = _ctx.Get()->DriverManagerGetConnection( - _jdbcConnectionString.c_str(), connection, &errInfo); + _jdbcConnectionString.c_str(), connection, errInfo); if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { BOOST_FAIL(errInfo.errMsg); } BOOST_REQUIRE(connection.Get()); + AutoCloseConnection autoCloseConnection(_ctx, connection); // get metadata + SharedPointer< GlobalJObject > databaseMetaData; + if (!_ctx.Get()->DocumentDbConnectionGetMetaData( + connection, databaseMetaData, errInfo)) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(databaseMetaData.Get()); + + std::string schemaName; + bool wasNull; + success = _ctx.Get()->DocumentDbDatabaseSchemaMetadataGetSchemaName( + databaseMetaData, schemaName, wasNull, errInfo); + if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + + BOOST_CHECK(!wasNull); + BOOST_CHECK_EQUAL(schemaName, "_default"); } BOOST_AUTO_TEST_CASE(TestConnectionGetMetaData) { From 701e790951d1080d46dd4e58beac88f6ab0b7c08 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 9 Feb 2022 12:03:36 -0800 Subject: [PATCH 138/165] [AD-521] refactor - change case of ssh to SSH for consistency --- src/odbc-test/src/java_test.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index c077835d7..0f993248f 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPort) { BOOST_REQUIRE(connection.Get()); AutoCloseConnection autoCloseConnection(_ctx, connection); - // see if ssh tunnel is active + // see if SSH tunnel is active bool isActive; success = _ctx.Get()->DocumentDbConnectionIsSshTunnelActive(connection, isActive, errInfo); // if tunnel is not shown as active, or operation not successful, BOOST FAIL @@ -229,7 +229,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPort) { } BOOST_CHECK(isActive); - // ssh tunnel confirmed to be active, get ssh tunnel local port + // SSH tunnel confirmed to be active, get SSH tunnel local port int32_t port; success = _ctx.Get()->DocumentDbConnectionGetSshLocalPort(connection, port, errInfo); if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { @@ -244,7 +244,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPort) { // TODO Enable when we can get external SSH tunnel working BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, * disabled()) { //BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive) { - // test when SSH tunnel is not active, the ssh tunnel port should be 0 + // test when SSH tunnel is not active, the SSH tunnel port should be 0 // TODO do things so SSH tunnel is not active, but connection is open PrepareContext(); BOOST_REQUIRE(_ctx.Get() != nullptr); @@ -260,7 +260,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, BOOST_REQUIRE(connection.Get()); AutoCloseConnection autoCloseConnection(_ctx, connection); - // check if ssh tunnel is not active + // check if SSH tunnel is not active bool isActive; success = _ctx.Get()->DocumentDbConnectionIsSshTunnelActive(connection, isActive, errInfo); // if SSH tunnel is active, or operation not successful, BOOST FAIL @@ -270,7 +270,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, BOOST_CHECK(!isActive); - // ssh tunnel confirmed to be not active, get ssh tunnel local port + // SSH tunnel confirmed to be not active, get SSH tunnel local port int32_t port; success = _ctx.Get()->DocumentDbConnectionGetSshLocalPort(connection, port, errInfo); if (errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { @@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, BOOST_FAIL(errMsg); } - // if SSH tunnel not active, ssh local port number should be 0 + // if SSH tunnel not active, SSH local port number should be 0 BOOST_CHECK_EQUAL(port, 0); } From 8c6dc914bd9b00a0340f43450fcfe7a21b68bb26 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 9 Feb 2022 13:56:32 -0800 Subject: [PATCH 139/165] [AD-589] address code review comments * rename DocumentDbConnectionGetMetaData to DocumentDbConnectionGetDatabaseMetaData --- src/odbc-test/src/java_test.cpp | 6 +++--- src/odbc/include/ignite/odbc/jni/java.h | 2 +- src/odbc/src/jni/java.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index e79b3a876..32d639cb4 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -282,7 +282,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, BOOST_CHECK_EQUAL(port, 0); } -BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { +BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetDatabaseMetaData) { PrepareContext(); BOOST_REQUIRE(_ctx.Get() != nullptr); @@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetMetaData) { // get metadata SharedPointer< GlobalJObject > databaseMetaData; - if (!_ctx.Get()->DocumentDbConnectionGetMetaData( + if (!_ctx.Get()->DocumentDbConnectionGetDatabaseMetaData( connection, databaseMetaData, errInfo)) { BOOST_FAIL(errInfo.errMsg); @@ -324,7 +324,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbDatabaseSchemaMetadataGetSchemaName) { // get metadata SharedPointer< GlobalJObject > databaseMetaData; - if (!_ctx.Get()->DocumentDbConnectionGetMetaData( + if (!_ctx.Get()->DocumentDbConnectionGetDatabaseMetaData( connection, databaseMetaData, errInfo)) { BOOST_FAIL(errInfo.errMsg); } diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index b7d5af24b..675e1c899 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -456,7 +456,7 @@ namespace ignite { bool DocumentDbConnectionIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo& errInfo); bool DocumentDbConnectionGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, int32_t& result, JniErrorInfo& errInfo); - bool DocumentDbConnectionGetMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo& errInfo); + bool DocumentDbConnectionGetDatabaseMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo& errInfo); bool DocumentDbDatabaseSchemaMetadataGetSchemaName(const SharedPointer< GlobalJObject >& databaseMetaData, std::string& value, bool& wasNull, JniErrorInfo& errInfo); diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 182b11ff8..1350389a0 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -877,7 +877,7 @@ namespace ignite return errInfo.code == IGNITE_JNI_ERR_SUCCESS; } - bool JniContext::DocumentDbConnectionGetMetaData( + bool JniContext::DocumentDbConnectionGetDatabaseMetaData( const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo& errInfo) { From 3f40401aaa11efe78119a3f2134956f2174479da Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Wed, 9 Feb 2022 14:22:49 -0800 Subject: [PATCH 140/165] [AD-589] change case from MetaData to Metadata to match Java method name --- src/odbc-test/src/java_test.cpp | 6 +++--- src/odbc/include/ignite/odbc/jni/java.h | 2 +- src/odbc/src/jni/java.cpp | 10 +++++----- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index 32d639cb4..cca302e5d 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -282,7 +282,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive, BOOST_CHECK_EQUAL(port, 0); } -BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetDatabaseMetaData) { +BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetDatabaseMetadata) { PrepareContext(); BOOST_REQUIRE(_ctx.Get() != nullptr); @@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetDatabaseMetaData) { // get metadata SharedPointer< GlobalJObject > databaseMetaData; - if (!_ctx.Get()->DocumentDbConnectionGetDatabaseMetaData( + if (!_ctx.Get()->DocumentDbConnectionGetDatabaseMetadata( connection, databaseMetaData, errInfo)) { BOOST_FAIL(errInfo.errMsg); @@ -324,7 +324,7 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbDatabaseSchemaMetadataGetSchemaName) { // get metadata SharedPointer< GlobalJObject > databaseMetaData; - if (!_ctx.Get()->DocumentDbConnectionGetDatabaseMetaData( + if (!_ctx.Get()->DocumentDbConnectionGetDatabaseMetadata( connection, databaseMetaData, errInfo)) { BOOST_FAIL(errInfo.errMsg); } diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index 675e1c899..6c3e06831 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -456,7 +456,7 @@ namespace ignite { bool DocumentDbConnectionIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo& errInfo); bool DocumentDbConnectionGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, int32_t& result, JniErrorInfo& errInfo); - bool DocumentDbConnectionGetDatabaseMetaData(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo& errInfo); + bool DocumentDbConnectionGetDatabaseMetadata(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo& errInfo); bool DocumentDbDatabaseSchemaMetadataGetSchemaName(const SharedPointer< GlobalJObject >& databaseMetaData, std::string& value, bool& wasNull, JniErrorInfo& errInfo); diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 1350389a0..9d516ad49 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -877,7 +877,7 @@ namespace ignite return errInfo.code == IGNITE_JNI_ERR_SUCCESS; } - bool JniContext::DocumentDbConnectionGetDatabaseMetaData( + bool JniContext::DocumentDbConnectionGetDatabaseMetadata( const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo& errInfo) { @@ -903,17 +903,17 @@ namespace ignite } bool JniContext::DocumentDbDatabaseSchemaMetadataGetSchemaName( - const SharedPointer< GlobalJObject >& databaseMetaData, + const SharedPointer< GlobalJObject >& databaseMetadata, std::string& value, bool& wasNull, JniErrorInfo& errInfo) { - if (!databaseMetaData.Get()) { + if (!databaseMetadata.Get()) { errInfo.code = IGNITE_JNI_ERR_GENERIC; - errInfo.errMsg = "DatabaseMetaData object must be set."; + errInfo.errMsg = "DatabaseMetadata object must be set."; return false; } JNIEnv* env = Attach(); jobject result = env->CallObjectMethod( - databaseMetaData.Get()->GetRef(), + databaseMetadata.Get()->GetRef(), jvm->GetMembers().m_DocumentDbDatabaseSchemaMetadataGetSchemaName); ExceptionCheck(env, &errInfo); From 84b4d831077bf4e013bdda6f519df2355820c1ae Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" Date: Thu, 10 Feb 2022 09:28:52 -0800 Subject: [PATCH 141/165] [AD-589] refactor: change from metaData to metadata changes occurred in: * DocumentDbConnectionGetDatabaseMetadata * DocumentDbDatabaseSchemaMetadataGetSchemaName * TestDocumentDbConnectionGetDatabaseMetadata * TestDocumentDbDatabaseSchemaMetadataGetSchemaName --- src/odbc-test/src/java_test.cpp | 14 +++++++------- src/odbc/include/ignite/odbc/jni/java.h | 4 ++-- src/odbc/src/jni/java.cpp | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index cca302e5d..b9f279fce 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -298,13 +298,13 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbConnectionGetDatabaseMetadata) { AutoCloseConnection autoCloseConnection(_ctx, connection); // get metadata - SharedPointer< GlobalJObject > databaseMetaData; + SharedPointer< GlobalJObject > databaseMetadata; if (!_ctx.Get()->DocumentDbConnectionGetDatabaseMetadata( - connection, databaseMetaData, + connection, databaseMetadata, errInfo)) { BOOST_FAIL(errInfo.errMsg); } - BOOST_REQUIRE(databaseMetaData.Get()); + BOOST_REQUIRE(databaseMetadata.Get()); } BOOST_AUTO_TEST_CASE(TestDocumentDbDatabaseSchemaMetadataGetSchemaName) { @@ -323,17 +323,17 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbDatabaseSchemaMetadataGetSchemaName) { AutoCloseConnection autoCloseConnection(_ctx, connection); // get metadata - SharedPointer< GlobalJObject > databaseMetaData; + SharedPointer< GlobalJObject > databaseMetadata; if (!_ctx.Get()->DocumentDbConnectionGetDatabaseMetadata( - connection, databaseMetaData, errInfo)) { + connection, databaseMetadata, errInfo)) { BOOST_FAIL(errInfo.errMsg); } - BOOST_REQUIRE(databaseMetaData.Get()); + BOOST_REQUIRE(databaseMetadata.Get()); std::string schemaName; bool wasNull; success = _ctx.Get()->DocumentDbDatabaseSchemaMetadataGetSchemaName( - databaseMetaData, schemaName, wasNull, errInfo); + databaseMetadata, schemaName, wasNull, errInfo); if (!success || errInfo.code != odbc::java::IGNITE_JNI_ERR_SUCCESS) { BOOST_FAIL(errInfo.errMsg); } diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index 6c3e06831..a1ce9c863 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -456,9 +456,9 @@ namespace ignite { bool DocumentDbConnectionIsSshTunnelActive(const SharedPointer< GlobalJObject >& connection, bool& isActive, JniErrorInfo& errInfo); bool DocumentDbConnectionGetSshLocalPort(const SharedPointer< GlobalJObject >& connection, int32_t& result, JniErrorInfo& errInfo); - bool DocumentDbConnectionGetDatabaseMetadata(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metaData, JniErrorInfo& errInfo); + bool DocumentDbConnectionGetDatabaseMetadata(const SharedPointer< GlobalJObject >& connection, SharedPointer< GlobalJObject >& metadata, JniErrorInfo& errInfo); - bool DocumentDbDatabaseSchemaMetadataGetSchemaName(const SharedPointer< GlobalJObject >& databaseMetaData, std::string& value, bool& wasNull, JniErrorInfo& errInfo); + bool DocumentDbDatabaseSchemaMetadataGetSchemaName(const SharedPointer< GlobalJObject >& databaseMetadata, std::string& value, bool& wasNull, JniErrorInfo& errInfo); bool DatabaseMetaDataGetTables( const SharedPointer< GlobalJObject >& databaseMetaData, diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index 9d516ad49..58fd5034e 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -879,7 +879,7 @@ namespace ignite bool JniContext::DocumentDbConnectionGetDatabaseMetadata( const SharedPointer< GlobalJObject >& connection, - SharedPointer< GlobalJObject >& metaData, + SharedPointer< GlobalJObject >& metadata, JniErrorInfo& errInfo) { if (!connection.Get()) { errInfo.code = IGNITE_JNI_ERR_GENERIC; @@ -893,11 +893,11 @@ namespace ignite ExceptionCheck(env, &errInfo); if (!result || errInfo.code != IGNITE_JNI_ERR_SUCCESS) { - metaData = nullptr; + metadata = nullptr; return false; } - metaData = SharedPointer< GlobalJObject >( + metadata = SharedPointer< GlobalJObject >( new GlobalJObject(env, env->NewGlobalRef(result))); return errInfo.code == IGNITE_JNI_ERR_SUCCESS; } From 8e7de0789d5a16134f15e9ad00852abf35c44761 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Fri, 13 May 2022 17:38:24 -0700 Subject: [PATCH 142/165] Birschick bq/sync up (#21) * Updating JDBC version (#72) * [AD-370] upload odbc driver build on push to develop (#71) * [AD-730] upload odbc driver build at push to develop * [AD-730] update github actions to upload with v3 * [AD-730] Test artifact upload action * temporarily comment out if statement guard to test upload-artifact github action * [AD-730] upload performance test executable * [AD-730] update readme * [AD-730] upload Release folder as artifact * our odbc needs more than just the ignite.odbc.dll to run properly * [AD-730] update to upload artifacts for release build * previously, I uploaded the Debug builds, but the Release build is the one that requires less dependencies. * [AD-730] add back if statment * add the if statement back in win-build.yml to ensure that the odbc driver performance artifact is only published when pushed to develop * [AD-730] fix typo of performance test plan Co-authored-by: affonsoBQ <67347924+affonsoBQ@users.noreply.github.com> Co-authored-by: Alina (Xi) Li <96995091+alinaliBQ@users.noreply.github.com> --- .github/workflows/linux-build.yml | 2 +- .github/workflows/mac-build.yml | 2 +- .github/workflows/win-build.yml | 33 ++++++++++++++----- README.md | 2 +- build_linux_debug64.sh | 2 +- build_linux_release64_deb.sh | 2 +- build_mac_debug64.sh | 2 +- build_mac_release64.sh | 2 +- scripts/build_windows.ps1 | 2 +- .../performance/Performance_Test_Plan.csv | 2 +- 10 files changed, 33 insertions(+), 18 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 205a20b31..de2b2489f 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -26,7 +26,7 @@ env: DOC_DB_PRIV_KEY_FILE: ~/certs/docdb-sshtunnel.pem DOC_DB_LOG_PATH: "${{github.workspace}}/build/odbc/logs" DOC_DB_LOG_LEVEL: "debug" - JDBC_DRIVER_VERSION: "1.2.1" + JDBC_DRIVER_VERSION: "1.2.3" JAVA_HOME: "/usr/lib/jvm/java-17-amazon-corretto/" jobs: diff --git a/.github/workflows/mac-build.yml b/.github/workflows/mac-build.yml index 52ecd9ff5..bf84ba934 100644 --- a/.github/workflows/mac-build.yml +++ b/.github/workflows/mac-build.yml @@ -27,7 +27,7 @@ env: DOC_DB_ODBC_INTEGRATION_TEST: 1 DOC_DB_LOG_PATH: "${{github.workspace}}/build/odbc/logs" DOC_DB_LOG_LEVEL: "debug" - JDBC_DRIVER_VERSION: "1.2.1" + JDBC_DRIVER_VERSION: "1.2.3" jobs: build-mac: diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index a48f3734f..a78b0f62d 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -29,7 +29,7 @@ env: DOC_DB_PRIV_KEY_FILE: ~/certs/docdb-sshtunnel.pem DOC_DB_LOG_PATH: "${{github.workspace}}/build/odbc/logs" DOC_DB_LOG_LEVEL: "debug" - JDBC_DRIVER_VERSION: "1.2.1" + JDBC_DRIVER_VERSION: "1.2.3" MONGO_IMPORT_COMMAND: "C:/ProgramData/chocolatey/lib/mongodb-database-tools/tools/mongodb-database-tools-windows-x86_64-100.5.2binmongoimport.exe" jobs: @@ -49,7 +49,7 @@ jobs: .\run_cppcheck.ps1 - name: upload-cppcheck-results if: failure() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: cppcheck-results path: cppcheck-results.log @@ -155,19 +155,19 @@ jobs: # .\scripts\prepare_ci_output.ps1 $Env:ODBC_BIN_PATH $Env:ODBC_LIB_PATH $Env:ODBC_BUILD_PATH # - name: upload-build # if: always() - # uses: actions/upload-artifact@v2 + # uses: actions/upload-artifact@v3 # with: # name: windows32-build # path: ci-output/build # - name: upload-installer # if: success() - # uses: actions/upload-artifact@v2 + # uses: actions/upload-artifact@v3 # with: # name: windows32-installer # path: ci-output/installer # - name: upload-test-results # if: always() - # uses: actions/upload-artifact@v2 + # uses: actions/upload-artifact@v3 # with: # name: windows-test-results # path: $CI_OUTPUT_PATH/test @@ -186,7 +186,7 @@ jobs: .\run_cppcheck.ps1 - name: upload-cppcheck-results if: failure() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: cppcheck-results path: cppcheck-results.log @@ -257,6 +257,20 @@ jobs: env: OPENSSL_ROOT_DIR: '${{env.VCPKG_ROOT}}/packages/openssl_x64-windows' + - name: Upload ODBC driver build at push to develop + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }} + uses: actions/upload-artifact@v3 + with: + name: docdb-odbc-driver + path: build/odbc/cmake/Release + + - name: Upload performance test at push to develop + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }} + uses: actions/upload-artifact@v3 + with: + name: performance + path: build/odbc/bin/Release/performance.exe + - name: register-driver run: | .\src\odbc\install\install_amd64.cmd ${{env.ODBC_BIN_PATH}}\ignite.odbc.dll @@ -290,13 +304,13 @@ jobs: # .\scripts\prepare_ci_output.ps1 $Env:ODBC_BIN_PATH $Env:ODBC_LIB_PATH $Env:ODBC_BUILD_PATH # - name: upload-build # if: always() - # uses: actions/upload-artifact@v2 + # uses: actions/upload-artifact@v3 # with: # name: windows64-build # path: ci-output/build # - name: upload-installer # if: success() - # uses: actions/upload-artifact@v2 + # uses: actions/upload-artifact@v3 # with: # name: windows64-installer # path: ci-output/installer @@ -398,10 +412,11 @@ jobs: - name: upload-coverage if: always() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: code-coverage path: coverage + # # The step below should be uncommented after the codecov is setup # - name: Upload Report to Codecov diff --git a/README.md b/README.md index fdd53c13d..175f95be8 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ Example: 2. Navigate to the `build\odbc\cmake` folder to use the generated solution file, `Ignite.C++.sln` to work on source code development and testing. 7. Set the environment variable `DOCUMENTDB_HOME`. On a developer's machine, set it to `\build\odbc\bin\Debug`. The - build script run above, downloads it to the `\build\odbc\bin\Debug\libs` folder. + build script run above, downloads the JDBC jar to the `\build\odbc\bin\Debug\libs` folder. 8. Open a **64-bit** command shell or **64-bit** PowerShell window, **as Administrator**, run the command below ``` .\\src\odbc\install\install_amd64.cmd \build\odbc\cmake\Debug\ignite.odbc.dll diff --git a/build_linux_debug64.sh b/build_linux_debug64.sh index f7d24db57..f10258fba 100755 --- a/build_linux_debug64.sh +++ b/build_linux_debug64.sh @@ -13,7 +13,7 @@ cd .. # Download the DocumentDB JDBC Driver if [ -z "$JDBC_DRIVER_VERSION" ]; then - JDBC_DRIVER_VERSION="1.2.1" + JDBC_DRIVER_VERSION="1.2.3" fi JDBC_DRIVER_FILENAME="documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" JDBC_DRIVER_FULLPATH="$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" diff --git a/build_linux_release64_deb.sh b/build_linux_release64_deb.sh index 8145543f6..459e761eb 100755 --- a/build_linux_release64_deb.sh +++ b/build_linux_release64_deb.sh @@ -10,7 +10,7 @@ cd .. # Download the DocumentDB JDBC Driver if [ -z "$JDBC_DRIVER_VERSION" ]; then - JDBC_DRIVER_VERSION="1.2.1" + JDBC_DRIVER_VERSION="1.2.3" fi JDBC_DRIVER_FILENAME="documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" JDBC_DRIVER_FULLPATH="$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" diff --git a/build_mac_debug64.sh b/build_mac_debug64.sh index 014713c69..41012aee7 100755 --- a/build_mac_debug64.sh +++ b/build_mac_debug64.sh @@ -13,7 +13,7 @@ cd .. # Download the DocumentDB JDBC Driver if [ -z "$JDBC_DRIVER_VERSION" ]; then - JDBC_DRIVER_VERSION="1.2.1" + JDBC_DRIVER_VERSION="1.2.3" fi JDBC_DRIVER_FILENAME="documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" JDBC_DRIVER_FULLPATH="$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" diff --git a/build_mac_release64.sh b/build_mac_release64.sh index f50e454d8..f9dc9c1fc 100755 --- a/build_mac_release64.sh +++ b/build_mac_release64.sh @@ -10,7 +10,7 @@ make -j 4 # Download the DocumentDB JDBC Driver if [ -z "$JDBC_DRIVER_VERSION" ]; then - JDBC_DRIVER_VERSION="1.2.1" + JDBC_DRIVER_VERSION="1.2.3" fi JDBC_DRIVER_FILENAME="documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" JDBC_DRIVER_FULLPATH="$DRIVER_BIN_DIR/libs/$JDBC_DRIVER_FILENAME" diff --git a/scripts/build_windows.ps1 b/scripts/build_windows.ps1 index a38cd378f..48621bfce 100644 --- a/scripts/build_windows.ps1 +++ b/scripts/build_windows.ps1 @@ -29,7 +29,7 @@ $DRIVER_BIN_DIR = "$DRIVER_BUILD_DIR\..\bin\$CONFIGURATION" New-Item -Path $DRIVER_BIN_DIR -ItemType Directory -Force | Out-Null # Download the JDBC driver -$JDBC_DRIVER_VERSION = if ($JDBC_DRIVER_VERSION -eq $null) { "1.2.1" } else { $JDBC_DRIVER_VERSION } +$JDBC_DRIVER_VERSION = if ($JDBC_DRIVER_VERSION -eq $null) { "1.2.3" } else { $JDBC_DRIVER_VERSION } $JDBC_DRIVER_FILENAME = "documentdb-jdbc-$JDBC_DRIVER_VERSION-all.jar" $JDBC_DRIVER_FULLPATH = "$DRIVER_BIN_DIR\libs\$JDBC_DRIVER_FILENAME" if (-not (Test-Path -Path $JDBC_DRIVER_FULLPATH -PathType Leaf)) { diff --git a/src/tests/performance/Performance_Test_Plan.csv b/src/tests/performance/Performance_Test_Plan.csv index 30c68f14c..2db20344e 100644 --- a/src/tests/performance/Performance_Test_Plan.csv +++ b/src/tests/performance/Performance_Test_Plan.csv @@ -36,7 +36,7 @@ SELECT LAST_DAY(createDate) FROM performance.employer_employees,10000,,LAST_DAY, "SELECT DATEDIFF(createDate, createDate) FROM performance.employer_employees",10000,,DATEDIFF,FALSE,10 "SELECT PERIOD_DIFF(createDate, createDate) FROM performance.employer_employees",10000,,PERIOD_DIFF,FALSE,10 SELECT YEAR(createDate) FROM performance.employer ,10000,,SELECT YEAR FROM,FALSE,10 -"SELECT YEAR(createDate),name,sector,createDate,emplyer__id FROM performance.employer ",10000,,"SELECT YEAR(createDate),name,sector,createDate,emplyer__id FROM performance.employer ",FALSE,10 +"SELECT YEAR(createDate),name,sector,createDate,employer__id FROM performance.employer ",10000,,"SELECT YEAR(createDate),name,sector,createDate,emplyer__id FROM performance.employer ",FALSE,10 SELECT YEAR(createDate) FROM performance.employer GROUP BY YEAR(createDate) ,10000,,SELECT YEAR FROM GROUP BY YEAR,FALSE,10 SELECT MONTH(createDate) FROM performance.employer ,10000,,SELECT MONTH FROM,FALSE,10 SELECT MONTH(createDate) FROM performance.employer GROUP BY MONTH(createDate) ,10000,,SELECT MONTH FROM GROUP BY MONTH,FALSE,10 From dc215fdb35dc8e1c0eafcbc0e421ae0a68d037a1 Mon Sep 17 00:00:00 2001 From: RoyZhang2022 <104782736+RoyZhang2022@users.noreply.github.com> Date: Tue, 17 May 2022 16:38:28 -0700 Subject: [PATCH 143/165] [AD-735] large dataset crash issue (#23) * first test * fix performance test crash * fix performance test crash * fix whitespace issue * rework based on comments --- .../include/performance_test_runner.h | 2 +- .../src/performance_test_runner.cpp | 26 ++++++------------- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/tests/performance/include/performance_test_runner.h b/src/tests/performance/include/performance_test_runner.h index 5841f768a..7b674859b 100644 --- a/src/tests/performance/include/performance_test_runner.h +++ b/src/tests/performance/include/performance_test_runner.h @@ -31,7 +31,7 @@ typedef SQLLEN SQLROWOFFSET; * GLOBAL CONSTANTS *******************************************************/ -#define BIND_SIZE 255 // used for SQLBindCol function +#define BIND_SIZE 512 // used for SQLBindCol function // CSV header definitions (input csv file must match) #define QUERY_HEADER "query" diff --git a/src/tests/performance/src/performance_test_runner.cpp b/src/tests/performance/src/performance_test_runner.cpp index 7b979a32c..1cf5a433f 100644 --- a/src/tests/performance/src/performance_test_runner.cpp +++ b/src/tests/performance/src/performance_test_runner.cpp @@ -406,13 +406,9 @@ void performance::PerformanceTestRunner::RecordExecBindFetch( SQLRETURN ret; SQLSMALLINT total_columns = 0; SQLROWSETSIZE row_count; - SQLROWSETSIZE rows_fetched; - SQLUSMALLINT* row_status; long long time_exec_ms; long long time_bind_fetch_ms; - - // Dynamic memory allocated - row_status = new SQLUSMALLINT[test_case.limit]; + std::vector< Col > cols; // Query std::string temp_str = @@ -429,7 +425,6 @@ void performance::PerformanceTestRunner::RecordExecBindFetch( auto time_exec_end = std::chrono::steady_clock::now(); if (ret != SQL_SUCCESS) { - delete[] row_status; LogAnyDiagnostics(SQL_HANDLE_STMT, *hstmt, ret); test_case.status = error; test_case.err_msg = "SQLExecDirect failed"; @@ -446,27 +441,24 @@ void performance::PerformanceTestRunner::RecordExecBindFetch( ret = SQLNumResultCols(*hstmt, &total_columns); if (ret != SQL_SUCCESS) { - delete[] row_status; LogAnyDiagnostics(SQL_HANDLE_STMT, *hstmt, ret); test_case.status = error; test_case.err_msg = "SQLNumResultCols failed"; return; // continue to next test case } - std::vector< std::vector< Col > > cols(total_columns); - for (size_t i = 0; i < cols.size(); i++) { - cols[i].resize(test_case.limit); + if (static_cast< size_t >(total_columns) > cols.size()) { + cols.resize(static_cast< size_t >(total_columns)); } // Bind and fetch and record time auto time_bind_fetch_start = std::chrono::steady_clock::now(); - for (size_t i = 0; i < cols.size(); i++) { + for (size_t i = 0; i < static_cast< size_t >(total_columns); i++) { ret = SQLBindCol(*hstmt, static_cast< SQLUSMALLINT >(i + 1), SQL_C_CHAR, - static_cast< SQLPOINTER >(&cols[i][0].data_dat[i]), - BIND_SIZE, &cols[i][0].data_len); + static_cast< SQLPOINTER >(&cols[i].data_dat[0]), + BIND_SIZE, &cols[i].data_len); if (ret != SQL_SUCCESS) { - delete[] row_status; LogAnyDiagnostics(SQL_HANDLE_STMT, *hstmt, ret); test_case.status = error; test_case.err_msg = "SQLBindCol failed"; @@ -474,11 +466,10 @@ void performance::PerformanceTestRunner::RecordExecBindFetch( } } - while (SQLExtendedFetch(*hstmt, SQL_FETCH_NEXT, 0, &rows_fetched, - row_status) - == SQL_SUCCESS) { + while (SQLFetch(*hstmt) == SQL_SUCCESS) { row_count++; } + auto time_bind_fetch_end = std::chrono::steady_clock::now(); // Store bind and fetch time @@ -490,7 +481,6 @@ void performance::PerformanceTestRunner::RecordExecBindFetch( test_case.time_ms.push_back(time_exec_ms + time_bind_fetch_ms); } - delete[] row_status; test_case.status = success; } From ba4b68f082542878524e9100d27f31045a2d14dc Mon Sep 17 00:00:00 2001 From: RoyZhang2022 Date: Thu, 19 May 2022 14:49:24 -0700 Subject: [PATCH 144/165] SQLPrimaryKey using JNI --- src/odbc-test/CMakeLists.txt | 1 + src/odbc/CMakeLists.txt | 1 + .../ignite/odbc/jni/database_metadata.h | 10 ++ src/odbc/include/ignite/odbc/jni/java.h | 7 ++ src/odbc/include/ignite/odbc/jni/result_set.h | 24 +++++ .../ignite/odbc/meta/primary_key_meta.h | 43 +++++--- .../ignite/odbc/query/primary_keys_query.h | 12 +++ src/odbc/src/jni/database_metadata.cpp | 13 +++ src/odbc/src/jni/java.cpp | 55 +++++++++- src/odbc/src/jni/result_set.cpp | 22 ++++ src/odbc/src/meta/primary_key_meta.cpp | 74 +++++++++++++ src/odbc/src/query/primary_keys_query.cpp | 101 ++++++++++++------ 12 files changed, 317 insertions(+), 46 deletions(-) create mode 100644 src/odbc/src/meta/primary_key_meta.cpp diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 50bd49326..a0ccdee6a 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -108,6 +108,7 @@ set(SOURCES ../odbc/src/log.cpp ../odbc/src/message.cpp ../odbc/src/meta/column_meta.cpp + ../odbc/src/meta/primary_key_meta.cpp ../odbc/src/meta/table_meta.cpp ../odbc/src/nested_tx_mode.cpp ../odbc/src/protocol_version.cpp diff --git a/src/odbc/CMakeLists.txt b/src/odbc/CMakeLists.txt index 695dfea53..2ba78267f 100644 --- a/src/odbc/CMakeLists.txt +++ b/src/odbc/CMakeLists.txt @@ -84,6 +84,7 @@ set(SOURCES src/app/application_data_buffer.cpp src/jni/result_set.cpp src/environment.cpp src/meta/column_meta.cpp + src/meta/primary_key_meta.cpp src/meta/table_meta.cpp src/odbc.cpp src/entry_points.cpp diff --git a/src/odbc/include/ignite/odbc/jni/database_metadata.h b/src/odbc/include/ignite/odbc/jni/database_metadata.h index 3cbe66329..47ad7eb8b 100644 --- a/src/odbc/include/ignite/odbc/jni/database_metadata.h +++ b/src/odbc/include/ignite/odbc/jni/database_metadata.h @@ -65,6 +65,16 @@ class DatabaseMetaData { const std::string& columnNamePattern, JniErrorInfo& errInfo); + /** + * Query the primary keys in the database according to the given + * search critera in catalog (not supported), schema, and + * table. + */ + SharedPointer< ResultSet > GetPrimaryKeys(const std::string& catalog, + const std::string& schema, + const std::string& table, + JniErrorInfo& errInfo); + private: /** * Constructs an instance of the DatabaseMetaData class. diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index 6c9a519b1..e1d61a212 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -288,6 +288,7 @@ struct JniMembers { jclass c_DatabaseMetaData; jmethodID m_DatabaseMetaDataGetTables; jmethodID m_DatabaseMetaDataGetColumns; + jmethodID m_DatabaseMetaDataGetPrimaryKeys; jclass c_List; jmethodID m_ListSize; @@ -529,6 +530,12 @@ class IGNITE_IMPORT_EXPORT JniContext { const std::string& tableNamePattern, const std::string& columnNamePattern, SharedPointer< GlobalJObject >& resultSet, JniErrorInfo& errInfo); + JniErrorCode DatabaseMetaDataGetPrimaryKeys( + const SharedPointer< GlobalJObject >& databaseMetaData, + const std::string& catalog, const std::string& schema, + const std::string& table, SharedPointer< GlobalJObject >& resultSet, + JniErrorInfo& errInfo); + JniErrorCode ResultSetClose(const SharedPointer< GlobalJObject >& resultSet, JniErrorInfo& errInfo); JniErrorCode ResultSetNext(const SharedPointer< GlobalJObject >& resultSet, diff --git a/src/odbc/include/ignite/odbc/jni/result_set.h b/src/odbc/include/ignite/odbc/jni/result_set.h index fe156261a..4ffdba32a 100644 --- a/src/odbc/include/ignite/odbc/jni/result_set.h +++ b/src/odbc/include/ignite/odbc/jni/result_set.h @@ -114,6 +114,30 @@ class ResultSet { JniErrorCode GetInt(const std::string& columnName, boost::optional< int >& value, JniErrorInfo& errInfo); + /** + * Gets a value on the current row of the result set for the + * given columnIndex (1-indexed). If a value exists, the value + * is set. If the value is null, the wasNull will be set to + * true, false, otherwise. + * + * @return a JniErrorCode indicating success or failure. + */ + JniErrorCode GetSmallInt(const int columnIndex, + boost::optional< int16_t >& value, + JniErrorInfo& errInfo); + + /** + * Gets a value on the current row of the result set for the + * given columnName. If a value exists, the value + * is set. If the value is null, the wasNull will be set to + * true, false, otherwise. + * + * @return a JniErrorCode indicating success or failure. + */ + JniErrorCode GetSmallInt(const std::string& columnName, + boost::optional< int16_t >& value, + JniErrorInfo& errInfo); + private: /** * Constructs a new instancee of ResultSet. diff --git a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h index dcceb01f3..8999103b0 100644 --- a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h +++ b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h @@ -23,8 +23,12 @@ #include #include "ignite/odbc/impl/binary/binary_reader_impl.h" +#include "ignite/odbc/jni/result_set.h" +#include "ignite/odbc/log.h" #include "ignite/odbc/utility.h" +using ignite::odbc::jni::ResultSet; + namespace ignite { namespace odbc { namespace meta { @@ -96,11 +100,18 @@ class PrimaryKeyMeta { return *this; } + /** + * Read resultset item. + * @param resultSet SharedPointer< ResultSet >. + * @paran errInfo JniErrorInfo. + */ + void Read(SharedPointer< ResultSet >& resultSet, JniErrorInfo& errInfo); + /** * Get catalog name. * @return Catalog name. */ - const std::string& GetCatalogName() const { + const boost::optional< std::string >& GetCatalogName() const { return catalog; } @@ -108,7 +119,7 @@ class PrimaryKeyMeta { * Get schema name. * @return Schema name. */ - const std::string& GetSchemaName() const { + const boost::optional< std::string >& GetSchemaName() const { return schema; } @@ -116,7 +127,7 @@ class PrimaryKeyMeta { * Get table name. * @return Table name. */ - const std::string& GetTableName() const { + const boost::optional< std::string >& GetTableName() const { return table; } @@ -124,7 +135,7 @@ class PrimaryKeyMeta { * Get column name. * @return Column name. */ - const std::string& GetColumnName() const { + const boost::optional< std::string >& GetColumnName() const { return table; } @@ -132,7 +143,7 @@ class PrimaryKeyMeta { * Get column sequence number in key. * @return Sequence number in key. */ - int16_t GetKeySeq() const { + boost::optional< int16_t > GetKeySeq() const { return keySeq; } @@ -140,32 +151,40 @@ class PrimaryKeyMeta { * Get key name. * @return Key name. */ - const std::string& GetKeyName() const { + const boost::optional< std::string >& GetKeyName() const { return keyName; } private: /** Catalog name. */ - std::string catalog; + boost::optional< std::string > catalog; /** Schema name. */ - std::string schema; + boost::optional< std::string > schema; /** Table name. */ - std::string table; + boost::optional< std::string > table; /** Collumn name. */ - std::string column; + boost::optional< std::string > column; /** Column sequence number in key. */ - int16_t keySeq; + boost::optional< int16_t > keySeq; /** Key name. */ - std::string keyName; + boost::optional< std::string > keyName; }; /** Table metadata vector alias. */ typedef std::vector< PrimaryKeyMeta > PrimaryKeyMetaVector; + +/** + * Read primary keys metadata collection. + * @param resultSet SharedPointer< ResultSet >. + * @param meta Collection. + */ +void ReadPrimaryKeysColumnMetaVector(SharedPointer< ResultSet >& resultSet, + PrimaryKeyMetaVector& meta); } // namespace meta } // namespace odbc } // namespace ignite diff --git a/src/odbc/include/ignite/odbc/query/primary_keys_query.h b/src/odbc/include/ignite/odbc/query/primary_keys_query.h index d120fe92c..b11b1e828 100644 --- a/src/odbc/include/ignite/odbc/query/primary_keys_query.h +++ b/src/odbc/include/ignite/odbc/query/primary_keys_query.h @@ -110,6 +110,15 @@ class PrimaryKeysQuery : public Query { private: IGNITE_NO_COPY_ASSIGNMENT(PrimaryKeysQuery); + /** + * Make get primary keys metadata requets and use response to set internal + * state. + * + * @return Operation result. + */ + virtual SqlResult::Type MakeRequestGetPrimaryKeysMeta(); + + /** Connection associated with the statement. */ Connection& connection; @@ -125,6 +134,9 @@ class PrimaryKeysQuery : public Query { /** Query executed. */ bool executed; + /** Fetched flag. */ + bool fetched; + /** Columns metadata. */ meta::ColumnMetaVector columnsMeta; diff --git a/src/odbc/src/jni/database_metadata.cpp b/src/odbc/src/jni/database_metadata.cpp index 2fd2fb90a..7a42bf149 100644 --- a/src/odbc/src/jni/database_metadata.cpp +++ b/src/odbc/src/jni/database_metadata.cpp @@ -58,6 +58,19 @@ SharedPointer< ResultSet > DatabaseMetaData::GetColumns( } return new ResultSet(_jniContext, resultSet); } + +SharedPointer< ResultSet > DatabaseMetaData::GetPrimaryKeys( + const std::string& catalog, const std::string& schema, + const std::string& table, JniErrorInfo& errInfo) { + SharedPointer< GlobalJObject > resultSet; + const std::vector< std::string > types; + JniErrorCode success = _jniContext.Get()->DatabaseMetaDataGetPrimaryKeys( + _databaseMetaData, catalog, schema, table, resultSet, errInfo); + if (success != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + return nullptr; + } + return new ResultSet(_jniContext, resultSet); +} } // namespace jni } // namespace odbc } // namespace ignite diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index e33dba231..b71c9b45b 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -257,7 +257,11 @@ JniMethod const M_DATABASE_META_DATA_GET_COLUMNS = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" "String;Ljava/lang/String;)Ljava/sql/ResultSet;", false); - +JniMethod const M_DATABASE_META_DATA_GET_PRIMARY_KEYS = + JniMethod("getPrimaryKeys", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" + "String;)Ljava/sql/ResultSet;", + false); const char* const C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnection"; JniMethod const M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT = @@ -660,6 +664,8 @@ void JniMembers::Initialize(JNIEnv* env) { FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_TABLES); m_DatabaseMetaDataGetColumns = FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_COLUMNS); + m_DatabaseMetaDataGetPrimaryKeys = + FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_PRIMARY_KEYS); c_Connection = FindClass(env, C_JAVA_SQL_CONNECTION); m_ConnectionClose = @@ -1414,6 +1420,53 @@ JniErrorCode JniContext::DatabaseMetaDataGetColumns( return errInfo.code; } +JniErrorCode JniContext::DatabaseMetaDataGetPrimaryKeys( + const SharedPointer< GlobalJObject >& databaseMetaData, + const std::string& catalog, const std::string& schema, + const std::string& table, SharedPointer< GlobalJObject >& resultSet, + JniErrorInfo& errInfo) { + LOG_DEBUG_MSG("DatabaseMetaDataGetPrimaryKeys is called"); + + if (databaseMetaData.Get() == nullptr) { + errInfo.code = JniErrorCode::IGNITE_JNI_ERR_GENERIC; + errInfo.errMsg = "DatabaseMetaData object must be set."; + + LOG_ERROR_MSG("DatabaseMetaDataGetPrimaryKeys exiting with error msg: " + << errInfo.errMsg); + + return errInfo.code; + } + + JNIEnv* env = Attach(); + jstring jCatalog = env->NewStringUTF(catalog.c_str()); + jstring jSchema = env->NewStringUTF(schema.c_str()); + jstring jTableName = env->NewStringUTF(table.c_str()); + + jobject result = env->CallObjectMethod( + databaseMetaData.Get()->GetRef(), + jvm->GetMembers().m_DatabaseMetaDataGetPrimaryKeys, jCatalog, jSchema, + jTableName); + ExceptionCheck(env, &errInfo); + + env->DeleteLocalRef(jCatalog); + env->DeleteLocalRef(jSchema); + env->DeleteLocalRef(jTableName); + + if (!result || errInfo.code != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + resultSet = nullptr; + LOG_ERROR_MSG( + "DatabaseMetaDataGetPrimaryKeys exiting with error. resultSet will be " + "null"); + return errInfo.code; + } + + resultSet = new GlobalJObject(env, env->NewGlobalRef(result)); + + LOG_DEBUG_MSG("DatabaseMetaDataGetPrimaryKeys exiting"); + + return errInfo.code; +} + JniErrorCode JniContext::ResultSetClose( const SharedPointer< GlobalJObject >& resultSet, JniErrorInfo& errInfo) { LOG_DEBUG_MSG("ResultSetClose is called"); diff --git a/src/odbc/src/jni/result_set.cpp b/src/odbc/src/jni/result_set.cpp index 20999cc5e..03a3c3463 100644 --- a/src/odbc/src/jni/result_set.cpp +++ b/src/odbc/src/jni/result_set.cpp @@ -85,6 +85,28 @@ JniErrorCode ResultSet::GetInt(const std::string& columnName, return _jniContext.Get()->ResultSetGetInt(_resultSet, columnName, value, errInfo); } + +JniErrorCode ResultSet::GetSmallInt(const int columnIndex, + boost::optional< int16_t >& value, + JniErrorInfo& errInfo) { + boost::optional< int > val; + JniErrorCode err = + _jniContext.Get()->ResultSetGetInt(_resultSet, columnIndex, val, errInfo); + if (val) + value = static_cast< int16_t >(*val); + return err; +} + +JniErrorCode ResultSet::GetSmallInt(const std::string& columnName, + boost::optional< int16_t >& value, + JniErrorInfo& errInfo) { + boost::optional< int > val; + JniErrorCode err = + _jniContext.Get()->ResultSetGetInt(_resultSet, columnName, val, errInfo); + if (val) + value = static_cast< int16_t >(*val); + return err; +} } // namespace jni } // namespace odbc } // namespace ignite diff --git a/src/odbc/src/meta/primary_key_meta.cpp b/src/odbc/src/meta/primary_key_meta.cpp new file mode 100644 index 000000000..c75ecb206 --- /dev/null +++ b/src/odbc/src/meta/primary_key_meta.cpp @@ -0,0 +1,74 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ignite/odbc/meta/primary_key_meta.h" + +#include "ignite/odbc/impl/binary/binary_common.h" +#include "ignite/odbc/common/utils.h" +#include "ignite/odbc/common_types.h" +#include "ignite/odbc/jni/java.h" +#include "ignite/odbc/system/odbc_constants.h" +#include "ignite/odbc/type_traits.h" + +namespace ignite { +namespace odbc { +namespace meta { + +const std::string TABLE_CAT = "TABLE_CAT"; +const std::string TABLE_SCHEM = "TABLE_SCHEM"; +const std::string TABLE_NAME = "TABLE_NAME"; +const std::string COLUMN_NAME = "COLUMN_NAME"; +const std::string KEY_SEQ = "KEY_SEQ"; +const std::string PK_NAME = "PK_NAME"; + + +void PrimaryKeyMeta::Read(SharedPointer< ResultSet >& resultSet, + JniErrorInfo& errInfo) { + resultSet.Get()->GetString(TABLE_CAT, catalog, errInfo); + resultSet.Get()->GetString(TABLE_SCHEM, schema, errInfo); + resultSet.Get()->GetString(TABLE_NAME, table, errInfo); + resultSet.Get()->GetString(COLUMN_NAME, column, errInfo); + resultSet.Get()->GetSmallInt(KEY_SEQ, keySeq, errInfo); + resultSet.Get()->GetString(PK_NAME, keyName, errInfo); +} + +void ReadPrimaryKeysColumnMetaVector(SharedPointer< ResultSet >& resultSet, + PrimaryKeyMetaVector& meta) { + meta.clear(); + + if (!resultSet.IsValid()) { + return; + } + + JniErrorInfo errInfo; + bool hasNext = false; + int32_t prevPosition = 0; + JniErrorCode errCode; + do { + errCode = resultSet.Get()->Next(hasNext, errInfo); + if (!hasNext || errCode != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + break; + } + + meta.emplace_back(PrimaryKeyMeta()); + meta.back().Read(resultSet, errInfo); + } while (hasNext); +} + +} // namespace meta +} // namespace odbc +} // namespace ignite \ No newline at end of file diff --git a/src/odbc/src/query/primary_keys_query.cpp b/src/odbc/src/query/primary_keys_query.cpp index cc7b1039b..de66907ab 100644 --- a/src/odbc/src/query/primary_keys_query.cpp +++ b/src/odbc/src/query/primary_keys_query.cpp @@ -72,18 +72,18 @@ PrimaryKeysQuery::PrimaryKeysQuery(diagnostic::DiagnosableAdapter& diag, const std::string sch(""); const std::string tbl(""); - columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_CAT", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_SCHEM", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_NAME", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_NAME", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ", IGNITE_TYPE_SHORT, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_CAT", JDBC_TYPE_VARCHAR, + Nullability::NULLABLE)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_SCHEM", JDBC_TYPE_VARCHAR, + Nullability::NULLABLE)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_NAME", JDBC_TYPE_VARCHAR, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_NAME", JDBC_TYPE_VARCHAR, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ", JDBC_TYPE_SMALLINT, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME", JDBC_TYPE_VARCHAR, + Nullability::NULLABLE)); } PrimaryKeysQuery::~PrimaryKeysQuery() { @@ -94,14 +94,16 @@ SqlResult::Type PrimaryKeysQuery::Execute() { if (executed) Close(); - meta.push_back( - meta::PrimaryKeyMeta(catalog, schema, table, "_KEY", 1, "_KEY")); + SqlResult::Type result = MakeRequestGetPrimaryKeysMeta(); - executed = true; + if (result == SqlResult::AI_SUCCESS) { + executed = true; + fetched = false; - cursor = meta.begin(); + cursor = meta.begin(); + } - return SqlResult::AI_SUCCESS; + return result; } const meta::ColumnMetaVector* PrimaryKeysQuery::GetMeta() { @@ -110,28 +112,27 @@ const meta::ColumnMetaVector* PrimaryKeysQuery::GetMeta() { SqlResult::Type PrimaryKeysQuery::FetchNextRow( app::ColumnBindingMap& columnBindings) { - // TODO: [AD-551] Adaptation SQLPrimaryKeys return tables PK - // https://bitquill.atlassian.net/browse/AD-551 - return SqlResult::AI_NO_DATA; - - //if (!executed) { - // diag.AddStatusRecord(SqlState::SHY010_SEQUENCE_ERROR, - // "Query was not executed."); + if (!executed) { + diag.AddStatusRecord(SqlState::SHY010_SEQUENCE_ERROR, + "Query was not executed."); - // return SqlResult::AI_ERROR; - //} + return SqlResult::AI_ERROR; + } - //if (cursor == meta.end()) - // return SqlResult::AI_NO_DATA; + if (!fetched) + fetched = true; + else + ++cursor; - //app::ColumnBindingMap::iterator it; + if (cursor == meta.end()) + return SqlResult::AI_NO_DATA; - //for (it = columnBindings.begin(); it != columnBindings.end(); ++it) - // GetColumn(it->first, it->second); + app::ColumnBindingMap::iterator it; - //++cursor; + for (it = columnBindings.begin(); it != columnBindings.end(); ++it) + GetColumn(it->first, it->second); - //return SqlResult::AI_SUCCESS; + return SqlResult::AI_SUCCESS; } SqlResult::Type PrimaryKeysQuery::GetColumn( @@ -190,6 +191,7 @@ SqlResult::Type PrimaryKeysQuery::Close() { meta.clear(); executed = false; + fetched = false; return SqlResult::AI_SUCCESS; } @@ -205,6 +207,39 @@ int64_t PrimaryKeysQuery::AffectedRows() const { SqlResult::Type PrimaryKeysQuery::NextResultSet() { return SqlResult::AI_NO_DATA; } + +SqlResult::Type PrimaryKeysQuery::MakeRequestGetPrimaryKeysMeta() { + IgniteError error; + SharedPointer< DatabaseMetaData > databaseMetaData = + connection.GetMetaData(error); + if (!databaseMetaData.IsValid() + || error.GetCode() != IgniteError::IGNITE_SUCCESS) { + diag.AddStatusRecord(error.GetText()); + return SqlResult::AI_ERROR; + } + + JniErrorInfo errInfo; + SharedPointer< ResultSet > resultSet = + databaseMetaData.Get()->GetPrimaryKeys(catalog, schema, table, errInfo); + if (!resultSet.IsValid() + || errInfo.code != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + diag.AddStatusRecord(errInfo.errMsg); + return SqlResult::AI_ERROR; + } + + meta::ReadPrimaryKeysColumnMetaVector(resultSet, meta); + + for (size_t i = 0; i < meta.size(); ++i) { + LOG_MSG("\n[" << i << "] SchemaName: " + << meta[i].GetSchemaName().get_value_or("") << "\n[" << i + << "] TableName: " + << meta[i].GetTableName().get_value_or("") << "\n[" << i + << "] ColumnName: " + << meta[i].GetColumnName().get_value_or("") << "\n[" << i + << "] ColumnType: not available"); + } + return SqlResult::AI_SUCCESS; +} } // namespace query } // namespace odbc } // namespace ignite From edb94599c77b9d60d68cbad9489838742f31805c Mon Sep 17 00:00:00 2001 From: RoyZhang2022 Date: Thu, 19 May 2022 15:32:58 -0700 Subject: [PATCH 145/165] odbc test failure fix --- src/odbc-test/src/api_robustness_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/src/api_robustness_test.cpp b/src/odbc-test/src/api_robustness_test.cpp index 7d53877e6..149e3ee7e 100644 --- a/src/odbc-test/src/api_robustness_test.cpp +++ b/src/odbc-test/src/api_robustness_test.cpp @@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(TestSQLPrimaryKeysEmpty) { BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); } ret = SQLFetch(stmt); - BOOST_CHECK_EQUAL(SQL_NO_DATA, ret); + BOOST_CHECK_EQUAL(SQL_SUCCESS, ret); } BOOST_AUTO_TEST_CASE(TestSQLSetStmtAttrGetStmtAttr) { From f7bb6dc528a0d20ac3169caf5cf8b0b8cceaf589 Mon Sep 17 00:00:00 2001 From: RoyZhang2022 Date: Thu, 19 May 2022 15:59:08 -0700 Subject: [PATCH 146/165] Revert "odbc test failure fix" This reverts commit edb94599c77b9d60d68cbad9489838742f31805c. --- src/odbc-test/src/api_robustness_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odbc-test/src/api_robustness_test.cpp b/src/odbc-test/src/api_robustness_test.cpp index 149e3ee7e..7d53877e6 100644 --- a/src/odbc-test/src/api_robustness_test.cpp +++ b/src/odbc-test/src/api_robustness_test.cpp @@ -163,7 +163,7 @@ BOOST_AUTO_TEST_CASE(TestSQLPrimaryKeysEmpty) { BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); } ret = SQLFetch(stmt); - BOOST_CHECK_EQUAL(SQL_SUCCESS, ret); + BOOST_CHECK_EQUAL(SQL_NO_DATA, ret); } BOOST_AUTO_TEST_CASE(TestSQLSetStmtAttrGetStmtAttr) { From 2b273f90e0b5acd266168504e942f14a5d551043 Mon Sep 17 00:00:00 2001 From: RoyZhang2022 Date: Thu, 19 May 2022 16:00:20 -0700 Subject: [PATCH 147/165] Revert "SQLPrimaryKey using JNI" This reverts commit ba4b68f082542878524e9100d27f31045a2d14dc. --- src/odbc-test/CMakeLists.txt | 1 - src/odbc/CMakeLists.txt | 1 - .../ignite/odbc/jni/database_metadata.h | 10 -- src/odbc/include/ignite/odbc/jni/java.h | 7 -- src/odbc/include/ignite/odbc/jni/result_set.h | 24 ----- .../ignite/odbc/meta/primary_key_meta.h | 43 +++----- .../ignite/odbc/query/primary_keys_query.h | 12 --- src/odbc/src/jni/database_metadata.cpp | 13 --- src/odbc/src/jni/java.cpp | 55 +--------- src/odbc/src/jni/result_set.cpp | 22 ---- src/odbc/src/meta/primary_key_meta.cpp | 74 ------------- src/odbc/src/query/primary_keys_query.cpp | 101 ++++++------------ 12 files changed, 46 insertions(+), 317 deletions(-) delete mode 100644 src/odbc/src/meta/primary_key_meta.cpp diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index a0ccdee6a..50bd49326 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -108,7 +108,6 @@ set(SOURCES ../odbc/src/log.cpp ../odbc/src/message.cpp ../odbc/src/meta/column_meta.cpp - ../odbc/src/meta/primary_key_meta.cpp ../odbc/src/meta/table_meta.cpp ../odbc/src/nested_tx_mode.cpp ../odbc/src/protocol_version.cpp diff --git a/src/odbc/CMakeLists.txt b/src/odbc/CMakeLists.txt index 2ba78267f..695dfea53 100644 --- a/src/odbc/CMakeLists.txt +++ b/src/odbc/CMakeLists.txt @@ -84,7 +84,6 @@ set(SOURCES src/app/application_data_buffer.cpp src/jni/result_set.cpp src/environment.cpp src/meta/column_meta.cpp - src/meta/primary_key_meta.cpp src/meta/table_meta.cpp src/odbc.cpp src/entry_points.cpp diff --git a/src/odbc/include/ignite/odbc/jni/database_metadata.h b/src/odbc/include/ignite/odbc/jni/database_metadata.h index 47ad7eb8b..3cbe66329 100644 --- a/src/odbc/include/ignite/odbc/jni/database_metadata.h +++ b/src/odbc/include/ignite/odbc/jni/database_metadata.h @@ -65,16 +65,6 @@ class DatabaseMetaData { const std::string& columnNamePattern, JniErrorInfo& errInfo); - /** - * Query the primary keys in the database according to the given - * search critera in catalog (not supported), schema, and - * table. - */ - SharedPointer< ResultSet > GetPrimaryKeys(const std::string& catalog, - const std::string& schema, - const std::string& table, - JniErrorInfo& errInfo); - private: /** * Constructs an instance of the DatabaseMetaData class. diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index e1d61a212..6c9a519b1 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -288,7 +288,6 @@ struct JniMembers { jclass c_DatabaseMetaData; jmethodID m_DatabaseMetaDataGetTables; jmethodID m_DatabaseMetaDataGetColumns; - jmethodID m_DatabaseMetaDataGetPrimaryKeys; jclass c_List; jmethodID m_ListSize; @@ -530,12 +529,6 @@ class IGNITE_IMPORT_EXPORT JniContext { const std::string& tableNamePattern, const std::string& columnNamePattern, SharedPointer< GlobalJObject >& resultSet, JniErrorInfo& errInfo); - JniErrorCode DatabaseMetaDataGetPrimaryKeys( - const SharedPointer< GlobalJObject >& databaseMetaData, - const std::string& catalog, const std::string& schema, - const std::string& table, SharedPointer< GlobalJObject >& resultSet, - JniErrorInfo& errInfo); - JniErrorCode ResultSetClose(const SharedPointer< GlobalJObject >& resultSet, JniErrorInfo& errInfo); JniErrorCode ResultSetNext(const SharedPointer< GlobalJObject >& resultSet, diff --git a/src/odbc/include/ignite/odbc/jni/result_set.h b/src/odbc/include/ignite/odbc/jni/result_set.h index 4ffdba32a..fe156261a 100644 --- a/src/odbc/include/ignite/odbc/jni/result_set.h +++ b/src/odbc/include/ignite/odbc/jni/result_set.h @@ -114,30 +114,6 @@ class ResultSet { JniErrorCode GetInt(const std::string& columnName, boost::optional< int >& value, JniErrorInfo& errInfo); - /** - * Gets a value on the current row of the result set for the - * given columnIndex (1-indexed). If a value exists, the value - * is set. If the value is null, the wasNull will be set to - * true, false, otherwise. - * - * @return a JniErrorCode indicating success or failure. - */ - JniErrorCode GetSmallInt(const int columnIndex, - boost::optional< int16_t >& value, - JniErrorInfo& errInfo); - - /** - * Gets a value on the current row of the result set for the - * given columnName. If a value exists, the value - * is set. If the value is null, the wasNull will be set to - * true, false, otherwise. - * - * @return a JniErrorCode indicating success or failure. - */ - JniErrorCode GetSmallInt(const std::string& columnName, - boost::optional< int16_t >& value, - JniErrorInfo& errInfo); - private: /** * Constructs a new instancee of ResultSet. diff --git a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h index 8999103b0..dcceb01f3 100644 --- a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h +++ b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h @@ -23,12 +23,8 @@ #include #include "ignite/odbc/impl/binary/binary_reader_impl.h" -#include "ignite/odbc/jni/result_set.h" -#include "ignite/odbc/log.h" #include "ignite/odbc/utility.h" -using ignite::odbc::jni::ResultSet; - namespace ignite { namespace odbc { namespace meta { @@ -100,18 +96,11 @@ class PrimaryKeyMeta { return *this; } - /** - * Read resultset item. - * @param resultSet SharedPointer< ResultSet >. - * @paran errInfo JniErrorInfo. - */ - void Read(SharedPointer< ResultSet >& resultSet, JniErrorInfo& errInfo); - /** * Get catalog name. * @return Catalog name. */ - const boost::optional< std::string >& GetCatalogName() const { + const std::string& GetCatalogName() const { return catalog; } @@ -119,7 +108,7 @@ class PrimaryKeyMeta { * Get schema name. * @return Schema name. */ - const boost::optional< std::string >& GetSchemaName() const { + const std::string& GetSchemaName() const { return schema; } @@ -127,7 +116,7 @@ class PrimaryKeyMeta { * Get table name. * @return Table name. */ - const boost::optional< std::string >& GetTableName() const { + const std::string& GetTableName() const { return table; } @@ -135,7 +124,7 @@ class PrimaryKeyMeta { * Get column name. * @return Column name. */ - const boost::optional< std::string >& GetColumnName() const { + const std::string& GetColumnName() const { return table; } @@ -143,7 +132,7 @@ class PrimaryKeyMeta { * Get column sequence number in key. * @return Sequence number in key. */ - boost::optional< int16_t > GetKeySeq() const { + int16_t GetKeySeq() const { return keySeq; } @@ -151,40 +140,32 @@ class PrimaryKeyMeta { * Get key name. * @return Key name. */ - const boost::optional< std::string >& GetKeyName() const { + const std::string& GetKeyName() const { return keyName; } private: /** Catalog name. */ - boost::optional< std::string > catalog; + std::string catalog; /** Schema name. */ - boost::optional< std::string > schema; + std::string schema; /** Table name. */ - boost::optional< std::string > table; + std::string table; /** Collumn name. */ - boost::optional< std::string > column; + std::string column; /** Column sequence number in key. */ - boost::optional< int16_t > keySeq; + int16_t keySeq; /** Key name. */ - boost::optional< std::string > keyName; + std::string keyName; }; /** Table metadata vector alias. */ typedef std::vector< PrimaryKeyMeta > PrimaryKeyMetaVector; - -/** - * Read primary keys metadata collection. - * @param resultSet SharedPointer< ResultSet >. - * @param meta Collection. - */ -void ReadPrimaryKeysColumnMetaVector(SharedPointer< ResultSet >& resultSet, - PrimaryKeyMetaVector& meta); } // namespace meta } // namespace odbc } // namespace ignite diff --git a/src/odbc/include/ignite/odbc/query/primary_keys_query.h b/src/odbc/include/ignite/odbc/query/primary_keys_query.h index b11b1e828..d120fe92c 100644 --- a/src/odbc/include/ignite/odbc/query/primary_keys_query.h +++ b/src/odbc/include/ignite/odbc/query/primary_keys_query.h @@ -110,15 +110,6 @@ class PrimaryKeysQuery : public Query { private: IGNITE_NO_COPY_ASSIGNMENT(PrimaryKeysQuery); - /** - * Make get primary keys metadata requets and use response to set internal - * state. - * - * @return Operation result. - */ - virtual SqlResult::Type MakeRequestGetPrimaryKeysMeta(); - - /** Connection associated with the statement. */ Connection& connection; @@ -134,9 +125,6 @@ class PrimaryKeysQuery : public Query { /** Query executed. */ bool executed; - /** Fetched flag. */ - bool fetched; - /** Columns metadata. */ meta::ColumnMetaVector columnsMeta; diff --git a/src/odbc/src/jni/database_metadata.cpp b/src/odbc/src/jni/database_metadata.cpp index 7a42bf149..2fd2fb90a 100644 --- a/src/odbc/src/jni/database_metadata.cpp +++ b/src/odbc/src/jni/database_metadata.cpp @@ -58,19 +58,6 @@ SharedPointer< ResultSet > DatabaseMetaData::GetColumns( } return new ResultSet(_jniContext, resultSet); } - -SharedPointer< ResultSet > DatabaseMetaData::GetPrimaryKeys( - const std::string& catalog, const std::string& schema, - const std::string& table, JniErrorInfo& errInfo) { - SharedPointer< GlobalJObject > resultSet; - const std::vector< std::string > types; - JniErrorCode success = _jniContext.Get()->DatabaseMetaDataGetPrimaryKeys( - _databaseMetaData, catalog, schema, table, resultSet, errInfo); - if (success != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { - return nullptr; - } - return new ResultSet(_jniContext, resultSet); -} } // namespace jni } // namespace odbc } // namespace ignite diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index b71c9b45b..e33dba231 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -257,11 +257,7 @@ JniMethod const M_DATABASE_META_DATA_GET_COLUMNS = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" "String;Ljava/lang/String;)Ljava/sql/ResultSet;", false); -JniMethod const M_DATABASE_META_DATA_GET_PRIMARY_KEYS = - JniMethod("getPrimaryKeys", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" - "String;)Ljava/sql/ResultSet;", - false); + const char* const C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnection"; JniMethod const M_DOCUMENTDB_CONNECTION_GET_SSH_LOCAL_PORT = @@ -664,8 +660,6 @@ void JniMembers::Initialize(JNIEnv* env) { FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_TABLES); m_DatabaseMetaDataGetColumns = FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_COLUMNS); - m_DatabaseMetaDataGetPrimaryKeys = - FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_PRIMARY_KEYS); c_Connection = FindClass(env, C_JAVA_SQL_CONNECTION); m_ConnectionClose = @@ -1420,53 +1414,6 @@ JniErrorCode JniContext::DatabaseMetaDataGetColumns( return errInfo.code; } -JniErrorCode JniContext::DatabaseMetaDataGetPrimaryKeys( - const SharedPointer< GlobalJObject >& databaseMetaData, - const std::string& catalog, const std::string& schema, - const std::string& table, SharedPointer< GlobalJObject >& resultSet, - JniErrorInfo& errInfo) { - LOG_DEBUG_MSG("DatabaseMetaDataGetPrimaryKeys is called"); - - if (databaseMetaData.Get() == nullptr) { - errInfo.code = JniErrorCode::IGNITE_JNI_ERR_GENERIC; - errInfo.errMsg = "DatabaseMetaData object must be set."; - - LOG_ERROR_MSG("DatabaseMetaDataGetPrimaryKeys exiting with error msg: " - << errInfo.errMsg); - - return errInfo.code; - } - - JNIEnv* env = Attach(); - jstring jCatalog = env->NewStringUTF(catalog.c_str()); - jstring jSchema = env->NewStringUTF(schema.c_str()); - jstring jTableName = env->NewStringUTF(table.c_str()); - - jobject result = env->CallObjectMethod( - databaseMetaData.Get()->GetRef(), - jvm->GetMembers().m_DatabaseMetaDataGetPrimaryKeys, jCatalog, jSchema, - jTableName); - ExceptionCheck(env, &errInfo); - - env->DeleteLocalRef(jCatalog); - env->DeleteLocalRef(jSchema); - env->DeleteLocalRef(jTableName); - - if (!result || errInfo.code != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { - resultSet = nullptr; - LOG_ERROR_MSG( - "DatabaseMetaDataGetPrimaryKeys exiting with error. resultSet will be " - "null"); - return errInfo.code; - } - - resultSet = new GlobalJObject(env, env->NewGlobalRef(result)); - - LOG_DEBUG_MSG("DatabaseMetaDataGetPrimaryKeys exiting"); - - return errInfo.code; -} - JniErrorCode JniContext::ResultSetClose( const SharedPointer< GlobalJObject >& resultSet, JniErrorInfo& errInfo) { LOG_DEBUG_MSG("ResultSetClose is called"); diff --git a/src/odbc/src/jni/result_set.cpp b/src/odbc/src/jni/result_set.cpp index 03a3c3463..20999cc5e 100644 --- a/src/odbc/src/jni/result_set.cpp +++ b/src/odbc/src/jni/result_set.cpp @@ -85,28 +85,6 @@ JniErrorCode ResultSet::GetInt(const std::string& columnName, return _jniContext.Get()->ResultSetGetInt(_resultSet, columnName, value, errInfo); } - -JniErrorCode ResultSet::GetSmallInt(const int columnIndex, - boost::optional< int16_t >& value, - JniErrorInfo& errInfo) { - boost::optional< int > val; - JniErrorCode err = - _jniContext.Get()->ResultSetGetInt(_resultSet, columnIndex, val, errInfo); - if (val) - value = static_cast< int16_t >(*val); - return err; -} - -JniErrorCode ResultSet::GetSmallInt(const std::string& columnName, - boost::optional< int16_t >& value, - JniErrorInfo& errInfo) { - boost::optional< int > val; - JniErrorCode err = - _jniContext.Get()->ResultSetGetInt(_resultSet, columnName, val, errInfo); - if (val) - value = static_cast< int16_t >(*val); - return err; -} } // namespace jni } // namespace odbc } // namespace ignite diff --git a/src/odbc/src/meta/primary_key_meta.cpp b/src/odbc/src/meta/primary_key_meta.cpp deleted file mode 100644 index c75ecb206..000000000 --- a/src/odbc/src/meta/primary_key_meta.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ignite/odbc/meta/primary_key_meta.h" - -#include "ignite/odbc/impl/binary/binary_common.h" -#include "ignite/odbc/common/utils.h" -#include "ignite/odbc/common_types.h" -#include "ignite/odbc/jni/java.h" -#include "ignite/odbc/system/odbc_constants.h" -#include "ignite/odbc/type_traits.h" - -namespace ignite { -namespace odbc { -namespace meta { - -const std::string TABLE_CAT = "TABLE_CAT"; -const std::string TABLE_SCHEM = "TABLE_SCHEM"; -const std::string TABLE_NAME = "TABLE_NAME"; -const std::string COLUMN_NAME = "COLUMN_NAME"; -const std::string KEY_SEQ = "KEY_SEQ"; -const std::string PK_NAME = "PK_NAME"; - - -void PrimaryKeyMeta::Read(SharedPointer< ResultSet >& resultSet, - JniErrorInfo& errInfo) { - resultSet.Get()->GetString(TABLE_CAT, catalog, errInfo); - resultSet.Get()->GetString(TABLE_SCHEM, schema, errInfo); - resultSet.Get()->GetString(TABLE_NAME, table, errInfo); - resultSet.Get()->GetString(COLUMN_NAME, column, errInfo); - resultSet.Get()->GetSmallInt(KEY_SEQ, keySeq, errInfo); - resultSet.Get()->GetString(PK_NAME, keyName, errInfo); -} - -void ReadPrimaryKeysColumnMetaVector(SharedPointer< ResultSet >& resultSet, - PrimaryKeyMetaVector& meta) { - meta.clear(); - - if (!resultSet.IsValid()) { - return; - } - - JniErrorInfo errInfo; - bool hasNext = false; - int32_t prevPosition = 0; - JniErrorCode errCode; - do { - errCode = resultSet.Get()->Next(hasNext, errInfo); - if (!hasNext || errCode != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { - break; - } - - meta.emplace_back(PrimaryKeyMeta()); - meta.back().Read(resultSet, errInfo); - } while (hasNext); -} - -} // namespace meta -} // namespace odbc -} // namespace ignite \ No newline at end of file diff --git a/src/odbc/src/query/primary_keys_query.cpp b/src/odbc/src/query/primary_keys_query.cpp index de66907ab..cc7b1039b 100644 --- a/src/odbc/src/query/primary_keys_query.cpp +++ b/src/odbc/src/query/primary_keys_query.cpp @@ -72,18 +72,18 @@ PrimaryKeysQuery::PrimaryKeysQuery(diagnostic::DiagnosableAdapter& diag, const std::string sch(""); const std::string tbl(""); - columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_CAT", JDBC_TYPE_VARCHAR, - Nullability::NULLABLE)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_SCHEM", JDBC_TYPE_VARCHAR, - Nullability::NULLABLE)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_NAME", JDBC_TYPE_VARCHAR, - Nullability::NO_NULL)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_NAME", JDBC_TYPE_VARCHAR, - Nullability::NO_NULL)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ", JDBC_TYPE_SMALLINT, - Nullability::NO_NULL)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME", JDBC_TYPE_VARCHAR, - Nullability::NULLABLE)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_CAT", IGNITE_TYPE_STRING, + Nullability::NULLABILITY_UNKNOWN)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_SCHEM", IGNITE_TYPE_STRING, + Nullability::NULLABILITY_UNKNOWN)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_NAME", IGNITE_TYPE_STRING, + Nullability::NULLABILITY_UNKNOWN)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "COLUMN_NAME", IGNITE_TYPE_STRING, + Nullability::NULLABILITY_UNKNOWN)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ", IGNITE_TYPE_SHORT, + Nullability::NULLABILITY_UNKNOWN)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME", IGNITE_TYPE_STRING, + Nullability::NULLABILITY_UNKNOWN)); } PrimaryKeysQuery::~PrimaryKeysQuery() { @@ -94,16 +94,14 @@ SqlResult::Type PrimaryKeysQuery::Execute() { if (executed) Close(); - SqlResult::Type result = MakeRequestGetPrimaryKeysMeta(); + meta.push_back( + meta::PrimaryKeyMeta(catalog, schema, table, "_KEY", 1, "_KEY")); - if (result == SqlResult::AI_SUCCESS) { - executed = true; - fetched = false; + executed = true; - cursor = meta.begin(); - } + cursor = meta.begin(); - return result; + return SqlResult::AI_SUCCESS; } const meta::ColumnMetaVector* PrimaryKeysQuery::GetMeta() { @@ -112,27 +110,28 @@ const meta::ColumnMetaVector* PrimaryKeysQuery::GetMeta() { SqlResult::Type PrimaryKeysQuery::FetchNextRow( app::ColumnBindingMap& columnBindings) { - if (!executed) { - diag.AddStatusRecord(SqlState::SHY010_SEQUENCE_ERROR, - "Query was not executed."); + // TODO: [AD-551] Adaptation SQLPrimaryKeys return tables PK + // https://bitquill.atlassian.net/browse/AD-551 + return SqlResult::AI_NO_DATA; - return SqlResult::AI_ERROR; - } + //if (!executed) { + // diag.AddStatusRecord(SqlState::SHY010_SEQUENCE_ERROR, + // "Query was not executed."); - if (!fetched) - fetched = true; - else - ++cursor; + // return SqlResult::AI_ERROR; + //} - if (cursor == meta.end()) - return SqlResult::AI_NO_DATA; + //if (cursor == meta.end()) + // return SqlResult::AI_NO_DATA; - app::ColumnBindingMap::iterator it; + //app::ColumnBindingMap::iterator it; - for (it = columnBindings.begin(); it != columnBindings.end(); ++it) - GetColumn(it->first, it->second); + //for (it = columnBindings.begin(); it != columnBindings.end(); ++it) + // GetColumn(it->first, it->second); - return SqlResult::AI_SUCCESS; + //++cursor; + + //return SqlResult::AI_SUCCESS; } SqlResult::Type PrimaryKeysQuery::GetColumn( @@ -191,7 +190,6 @@ SqlResult::Type PrimaryKeysQuery::Close() { meta.clear(); executed = false; - fetched = false; return SqlResult::AI_SUCCESS; } @@ -207,39 +205,6 @@ int64_t PrimaryKeysQuery::AffectedRows() const { SqlResult::Type PrimaryKeysQuery::NextResultSet() { return SqlResult::AI_NO_DATA; } - -SqlResult::Type PrimaryKeysQuery::MakeRequestGetPrimaryKeysMeta() { - IgniteError error; - SharedPointer< DatabaseMetaData > databaseMetaData = - connection.GetMetaData(error); - if (!databaseMetaData.IsValid() - || error.GetCode() != IgniteError::IGNITE_SUCCESS) { - diag.AddStatusRecord(error.GetText()); - return SqlResult::AI_ERROR; - } - - JniErrorInfo errInfo; - SharedPointer< ResultSet > resultSet = - databaseMetaData.Get()->GetPrimaryKeys(catalog, schema, table, errInfo); - if (!resultSet.IsValid() - || errInfo.code != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { - diag.AddStatusRecord(errInfo.errMsg); - return SqlResult::AI_ERROR; - } - - meta::ReadPrimaryKeysColumnMetaVector(resultSet, meta); - - for (size_t i = 0; i < meta.size(); ++i) { - LOG_MSG("\n[" << i << "] SchemaName: " - << meta[i].GetSchemaName().get_value_or("") << "\n[" << i - << "] TableName: " - << meta[i].GetTableName().get_value_or("") << "\n[" << i - << "] ColumnName: " - << meta[i].GetColumnName().get_value_or("") << "\n[" << i - << "] ColumnType: not available"); - } - return SqlResult::AI_SUCCESS; -} } // namespace query } // namespace odbc } // namespace ignite From 347b02a446355da678faf79e93ef48d84638acc0 Mon Sep 17 00:00:00 2001 From: "Alina (Xi) Li" <96995091+alinaliBQ@users.noreply.github.com> Date: Thu, 26 May 2022 14:20:08 -0700 Subject: [PATCH 148/165] [AD-550] Adapt Foreign Keys (#24) * [AD-550] JNI implementation for getImportedKeys * [AD-550] update Pull Request Template * added reviewees Roy Zhang and Micthell Elholm * [AD-550] add todo note to unit test * [AD-550] define GetImportedKeys in database_metadata.h/.cpp * add ODBC wrapper code to the JNI call for GetImportedKeys * [AD-550] initialize string vars to be empty string in column_metadata_query * [AD-550] modify ForeignKeysQuery to accept 3 arguments only * modified ForeignKeysQuery to only accept catalog, schema, and table, as other fields are not needed. * [AD-550] update column metadata for foreign keys * [AD-550] fix typo in primary_key_meta.h * [AD-550] define vars for foreign key meta * [AD-550] add getter functions for vars in foreign_key_meta.h * [AD-550] support vars in foreign key meta to be optional * [AD-550] add headers for boost optional * [AD-550] add headers and constructors for foreign key meta * added ForeignKeyMeta constructor, and copy constructor *added ForeignKeyMeta destructor * define ForeignKeyMetaVector * basically, complete foreign_key_meta.h * [AD-550] implement resultset.getSmallInt * implement resultset.getSmallInt taking column indices or column names as parameters * make ColumnMeta::dataType be updated with resultSet.Get()->GetSmallInt to simplify code and readbility * [AD-550] Add foreign_key_meta.cpp * implemented functions: ReadForeignKeysColumnMetaVector ForeignKeyMeta::Read * [AD-550] update CMakeLists to include foreign_key_meta.cpp * [AD-550] implement MakeRequestGetForeignKeysMeta * MakeRequestGetForeignKeysMeta calls GetImportedKeys to get Jni ResultSet object for foreign keys, and then reads the resultSet object to fill in the meta object. * [AD-550] update ForeignKeysQuery::DataAvailable and ForeignKeysQuery::Close * update meta object accordingly whenForeignKeysQuery::Close() is called. * return boolean for whether data is available based on meta object * [AD-550] implement ForeignKeysQuery::Execute and FetchNextRow * the code for ForeignKeysQuery::Execute and ForeignKeysQuery::FetchNextRow is based on ColumnMetadataQuery::Execute and ColumnMetadataQuery::FetchNextRow * [AD-550] fix Mac and Linux build * remove extra qualification on GetSmallInt function * [AD-550] implement ForeignKeysQuery::GetColumn * had formatting changes as well * [AD-550] JNI implementation for getImportedKeys * [AD-550] update Pull Request Template * added reviewees Roy Zhang and Micthell Elholm * [AD-550] add todo note to unit test * [AD-550] define GetImportedKeys in database_metadata.h/.cpp * add ODBC wrapper code to the JNI call for GetImportedKeys * [AD-550] initialize string vars to be empty string in column_metadata_query * [AD-550] modify ForeignKeysQuery to accept 3 arguments only * modified ForeignKeysQuery to only accept catalog, schema, and table, as other fields are not needed. * [AD-550] update column metadata for foreign keys * [AD-550] fix typo in primary_key_meta.h * [AD-550] define vars for foreign key meta * [AD-550] add getter functions for vars in foreign_key_meta.h * [AD-550] support vars in foreign key meta to be optional * [AD-550] add headers for boost optional * [AD-550] add headers and constructors for foreign key meta * added ForeignKeyMeta constructor, and copy constructor *added ForeignKeyMeta destructor * define ForeignKeyMetaVector * basically, complete foreign_key_meta.h * [AD-550] implement resultset.getSmallInt * implement resultset.getSmallInt taking column indices or column names as parameters * make ColumnMeta::dataType be updated with resultSet.Get()->GetSmallInt to simplify code and readbility * [AD-550] Add foreign_key_meta.cpp * implemented functions: ReadForeignKeysColumnMetaVector ForeignKeyMeta::Read * [AD-550] update CMakeLists to include foreign_key_meta.cpp * [AD-550] implement MakeRequestGetForeignKeysMeta * MakeRequestGetForeignKeysMeta calls GetImportedKeys to get Jni ResultSet object for foreign keys, and then reads the resultSet object to fill in the meta object. * [AD-550] update ForeignKeysQuery::DataAvailable and ForeignKeysQuery::Close * update meta object accordingly whenForeignKeysQuery::Close() is called. * return boolean for whether data is available based on meta object * [AD-550] implement ForeignKeysQuery::Execute and FetchNextRow * the code for ForeignKeysQuery::Execute and ForeignKeysQuery::FetchNextRow is based on ColumnMetadataQuery::Execute and ColumnMetadataQuery::FetchNextRow * [AD-550] fix Mac and Linux build * remove extra qualification on GetSmallInt function * [AD-550] implement ForeignKeysQuery::GetColumn * had formatting changes as well * [AD-550] update docs for foreign_keys_query.h * [AD-550] refine SQLForeignKey call * [AD-550] add draft foreign key test for JNI test * [AD-550] add test tables for jni test * [AD-550] update test TestDocumentDbDatabaseMetaDataGetImportedKeys * update test to query virtual table jni_test_001_sub_doc * [AD-550] add SQLForeignKeys sql api test * [AD-550] add logs for ReadForeignKeysColumnMetaVector * PK* variables will contain the list of foreign keys in the specified table * [AD-550] reformat jni_test * [AD-550] implement TestDatabaseMetaDataGetImportedKeys for java_test * [AD-550] add test document meta_queries_test_002_with_array * this document will be used to test SQLForeignKeys in meta_queries_test * [AD-550] refactor TestSQLForeignKeys test * reason: I see that `SQLCHAR empty[] = "";` is used in meta_queries_test, and I think that might be a better way of writing the parameters * [AD-550] add test for SQLForeignKeys in meta_queries_test tests added: * TestGetDataWithForeignKeysReturnsOneFromLocalServer * TestGetDataWithForeignKeysReturnsNone * they use test table meta_queries_test_002_with_array * [AD-550] clean up * add doc for SQLForeignKeys * remove comments * [AD-550] remove commented out code * [AD-550] remove unneeded commented out code * [AD-550] make ODBC pass nullptr for JString catalog and schema for SQLForeignKeys * in getImportedKeys, null boost::optional strings will be passed as nullptr to JDBC * make jni test and java test pass null boost::optional strings to JNI calls for getImportedKeys * ODBC now passes boost::optional strings foreignCatalog and foreignSchema to ExecuteGetForeignKeysQuery function. * [AD-550] add if check for sqlStrLen * if sqlString is empty, return boost::none * [AD-550] debug `choco install cppcheck -y` not working on GitHub Actions * [AD-550] add tests for testing empty string parameters * added Java test TestDatabaseMetaDataGetImportedKeysReturnsNone * added Jni test TestDocumentDbDatabaseMetaDataGetImportedKeysReturnsNone * [AD-550] disable cppcheck * created [AD-752](https://bitquill.atlassian.net/browse/AD-752) to investigate it further. * [AD-550] change the place for code doc for function SQLForeignKeys * [AD-550] update if statement check of SqlStringToOptString * to resolve code review comment * [AD-550] resolve code review comment * The sqlStrLen is an int32_t, so "!sqlStrLen" can be removed * [AD-550] make boost optional strings constant where needed * previously, I changed `const std::string` to `boost::optional< std::string >` in some areas, and this is now fixed by replacing the latter with `boost::optional< const std::string >` * [AD-550] SqlStringToOptString fix * also fixed SqlStringToConstOptString * reason: SQL_NTS is a flag that indicates that the string passed is a null-terminated string. * [AD-550] make tests pass null to SQLForeignKeys * [AD-550] add test case for TestGetDataWithForeignKeysReturnsNone * even with the correct table name, as long as empty strings are passed as catalog/schema, SQL_NO_DATA should be returned * [AD-550] update SqlStringToOptString * [AD-550] update TestSQLForeignKeys to pass NULL as parameters properly * [AD-550] move `const` out of `boost::optional< const std::string >` * reason: `const boost::optional< std::string >` works better than `boost::optional< const std::string >`. * this commit is to resolve code review comments * [AD-550] add meta_queries test that passes catalog as empty string * [AD-550] Set `fetched` to false in ForeignKeysQuery::Close() * [AD-550] add explicit conversion to boost::optional variable initialization * [AD-550] resolve code review comment * remove duplicate code * [AD-550] remove function * removed unneeded function: SqlStringToConstOptString --- .github/PULL_REQUEST_TEMPLATE.md | 2 + .github/workflows/win-build.yml | 64 ++-- src/odbc-test/CMakeLists.txt | 1 + src/odbc-test/input/jni_test_001_sub.json | 6 + .../input/jni_test_001_with_array.json | 9 + .../meta_queries_test_002_with_array.json | 9 + src/odbc-test/src/api_robustness_test.cpp | 21 +- src/odbc-test/src/java_test.cpp | 362 ++++++++++++++++++ src/odbc-test/src/jni_test.cpp | 206 ++++++++++ src/odbc-test/src/meta_queries_test.cpp | 80 ++++ src/odbc/CMakeLists.txt | 1 + src/odbc/include/ignite/odbc.h | 6 + .../ignite/odbc/jni/database_metadata.h | 10 + src/odbc/include/ignite/odbc/jni/java.h | 8 + src/odbc/include/ignite/odbc/jni/result_set.h | 22 ++ .../ignite/odbc/meta/foreign_key_meta.h | 318 +++++++++++++++ .../ignite/odbc/meta/primary_key_meta.h | 2 +- .../ignite/odbc/query/foreign_keys_query.h | 52 +-- src/odbc/include/ignite/odbc/statement.h | 11 +- src/odbc/include/ignite/odbc/utility.h | 13 + src/odbc/src/jni/database_metadata.cpp | 14 + src/odbc/src/jni/java.cpp | 54 +++ src/odbc/src/jni/result_set.cpp | 22 ++ src/odbc/src/meta/column_meta.cpp | 5 +- src/odbc/src/meta/foreign_key_meta.cpp | 89 +++++ src/odbc/src/odbc.cpp | 35 +- src/odbc/src/query/column_metadata_query.cpp | 4 +- src/odbc/src/query/foreign_keys_query.cpp | 294 +++++++++++--- src/odbc/src/statement.cpp | 16 +- src/odbc/src/utility.cpp | 21 + 30 files changed, 1615 insertions(+), 142 deletions(-) create mode 100644 src/odbc-test/input/jni_test_001_sub.json create mode 100644 src/odbc-test/input/jni_test_001_with_array.json create mode 100644 src/odbc-test/input/meta_queries_test_002_with_array.json create mode 100644 src/odbc/include/ignite/odbc/meta/foreign_key_meta.h create mode 100644 src/odbc/src/meta/foreign_key_meta.cpp diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 250b9fcfe..b6fd34de2 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -17,4 +17,6 @@ @alinaliBQ @andiem-bq @birschick-bq +@mitchell-elholm +@RoyZhang2022 diff --git a/.github/workflows/win-build.yml b/.github/workflows/win-build.yml index a78b0f62d..c53caad3b 100644 --- a/.github/workflows/win-build.yml +++ b/.github/workflows/win-build.yml @@ -37,22 +37,24 @@ jobs: runs-on: windows-2022 steps: - uses: actions/checkout@v2 - - name: setup-cppcheck - id: setup_cppcheck - run: | - choco install cppcheck -y - echo "C:\Program Files\Cppcheck" >> $env:GITHUB_PATH + # TODO Reactivate cppcheck + # https://bitquill.atlassian.net/browse/AD-752 + # - name: setup-cppcheck + # id: setup_cppcheck + # run: | + # choco install cppcheck -y -d + # echo "C:\Program Files\Cppcheck" >> $env:GITHUB_PATH - - name: run-cppcheck - id: run-cppcheck - run: | - .\run_cppcheck.ps1 - - name: upload-cppcheck-results - if: failure() - uses: actions/upload-artifact@v3 - with: - name: cppcheck-results - path: cppcheck-results.log + # - name: run-cppcheck + # id: run-cppcheck + # run: | + # .\run_cppcheck.ps1 + # - name: upload-cppcheck-results + # if: failure() + # uses: actions/upload-artifact@v3 + # with: + # name: cppcheck-results + # path: cppcheck-results.log - name: Get Java distribution uses: actions/setup-java@v2 with: @@ -175,21 +177,23 @@ jobs: runs-on: windows-2022 steps: - uses: actions/checkout@v2 - - name: run-cppcheck - id: setup_cppcheck - run: | - choco install cppcheck -y - echo "C:\Program Files\Cppcheck" >> $env:GITHUB_PATH - - name: run-cppcheck - id: run-cppcheck - run: | - .\run_cppcheck.ps1 - - name: upload-cppcheck-results - if: failure() - uses: actions/upload-artifact@v3 - with: - name: cppcheck-results - path: cppcheck-results.log + # TODO Reactivate cppcheck + # https://bitquill.atlassian.net/browse/AD-752 + # - name: run-cppcheck + # id: setup_cppcheck + # run: | + # choco install cppcheck -y -d + # echo "C:\Program Files\Cppcheck" >> $env:GITHUB_PATH + # - name: run-cppcheck + # id: run-cppcheck + # run: | + # .\run_cppcheck.ps1 + # - name: upload-cppcheck-results + # if: failure() + # uses: actions/upload-artifact@v3 + # with: + # name: cppcheck-results + # path: cppcheck-results.log - name: Get Java distribution uses: actions/setup-java@v2 with: diff --git a/src/odbc-test/CMakeLists.txt b/src/odbc-test/CMakeLists.txt index 50bd49326..23943aa88 100644 --- a/src/odbc-test/CMakeLists.txt +++ b/src/odbc-test/CMakeLists.txt @@ -108,6 +108,7 @@ set(SOURCES ../odbc/src/log.cpp ../odbc/src/message.cpp ../odbc/src/meta/column_meta.cpp + ../odbc/src/meta/foreign_key_meta.cpp ../odbc/src/meta/table_meta.cpp ../odbc/src/nested_tx_mode.cpp ../odbc/src/protocol_version.cpp diff --git a/src/odbc-test/input/jni_test_001_sub.json b/src/odbc-test/input/jni_test_001_sub.json new file mode 100644 index 000000000..3692e46ea --- /dev/null +++ b/src/odbc-test/input/jni_test_001_sub.json @@ -0,0 +1,6 @@ +[ + { + "_id": "key", + "doc": {"field": 1} + } +] diff --git a/src/odbc-test/input/jni_test_001_with_array.json b/src/odbc-test/input/jni_test_001_with_array.json new file mode 100644 index 000000000..33965d216 --- /dev/null +++ b/src/odbc-test/input/jni_test_001_with_array.json @@ -0,0 +1,9 @@ +[ + { + "_id": 3, + "field": "string", + "array": [ + 1, 2, 3 + ] + } +] diff --git a/src/odbc-test/input/meta_queries_test_002_with_array.json b/src/odbc-test/input/meta_queries_test_002_with_array.json new file mode 100644 index 000000000..33965d216 --- /dev/null +++ b/src/odbc-test/input/meta_queries_test_002_with_array.json @@ -0,0 +1,9 @@ +[ + { + "_id": 3, + "field": "string", + "array": [ + 1, 2, 3 + ] + } +] diff --git a/src/odbc-test/src/api_robustness_test.cpp b/src/odbc-test/src/api_robustness_test.cpp index 7d53877e6..711dd8b6b 100644 --- a/src/odbc-test/src/api_robustness_test.cpp +++ b/src/odbc-test/src/api_robustness_test.cpp @@ -396,6 +396,25 @@ BOOST_AUTO_TEST_CASE(TestSQLNumResultCols) { ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt); } +BOOST_AUTO_TEST_CASE(TestSQLForeignKeys) { + std::string dsnConnectionString; + CreateDsnConnectionStringForLocalServer(dsnConnectionString); + + Connect(dsnConnectionString); + + SQLCHAR fkTableName[] = "jni_test_001_sub_doc"; + + SQLRETURN ret = + SQLForeignKeys(stmt, NULL, 0, /* Primary catalog */ + NULL, 0, /* Primary schema */ + NULL, 0, /* Primary table */ + NULL, 0, /* Foreign catalog */ + NULL, 0, /* Foreign schema */ + fkTableName, sizeof(fkTableName)); /* Foreign table */ + + ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_STMT, stmt); +} + BOOST_AUTO_TEST_CASE(TestSQLTables, *disabled()) { // There are no checks because we do not really care what is the result of // these calls as long as they do not cause segmentation fault. @@ -693,7 +712,7 @@ BOOST_AUTO_TEST_CASE(TestSQLRowCount, *disabled()) { SQLRowCount(stmt, 0); } -BOOST_AUTO_TEST_CASE(TestSQLForeignKeys, *disabled()) { +BOOST_AUTO_TEST_CASE(TestSQLForeignKeysSegFault, *disabled()) { // There are no checks because we do not really care what is the result of // these calls as long as they do not cause segmentation fault. diff --git a/src/odbc-test/src/java_test.cpp b/src/odbc-test/src/java_test.cpp index 3acb6de71..f8da22c99 100644 --- a/src/odbc-test/src/java_test.cpp +++ b/src/odbc-test/src/java_test.cpp @@ -653,4 +653,366 @@ BOOST_AUTO_TEST_CASE(TestDatabaseMetaDataGetColumns) { } } +BOOST_AUTO_TEST_CASE(TestDatabaseMetaDataGetImportedKeys) { + PrepareContext(); + BOOST_REQUIRE(_ctx.Get() != nullptr); + + JniErrorInfo errInfo; + SharedPointer< GlobalJObject > connection; + // get connection + JniErrorCode success = _ctx.Get()->DriverManagerGetConnection( + _jdbcConnectionString.c_str(), connection, errInfo); + if (success != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(connection.Get()); + AutoCloseConnection autoCloseConnection(_ctx, connection); + + // get databaseMetaData object + SharedPointer< GlobalJObject > databaseMetaData; + if (_ctx.Get()->ConnectionGetMetaData(connection, databaseMetaData, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(databaseMetaData.Get()); + + const boost::optional< std::string > catalog = boost::none; + const boost::optional< std::string > schema = boost::none; + std::string fkTableName = "jni_test_001_sub_doc"; + SharedPointer< GlobalJObject > resultSet; + if (_ctx.Get()->DatabaseMetaDataGetImportedKeys( + databaseMetaData, catalog, schema, fkTableName, resultSet, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(resultSet.Get()); + AutoCloseResultSet autoCloseResultSet(_ctx, resultSet); + + // Get first + bool hasNext; + if (_ctx.Get()->ResultSetNext(resultSet, hasNext, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(hasNext); + + std::string table = "jni_test_001_sub"; + std::string fkColumn = "jni_test_001_sub__id"; + + int i = 1; + while (hasNext) { + boost::optional< std::string > value; + // TABLE_CAT (i.e., catalog - always NULL in our case) + if (_ctx.Get()->ResultSetGetString(resultSet, 1, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + // grab string from first column + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(!value); + + // PKTABLE_CAT (i.e., catalog - always NULL in our case) + if (_ctx.Get()->ResultSetGetString(resultSet, "PKTABLE_CAT", value, + errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { // grab string from first + // column by name + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(!value); + + // PKTABLE_SCHEM (i.e., database) + if (_ctx.Get()->ResultSetGetString(resultSet, 2, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(DATABASE_NAME, *value); + + // PKTABLE_SCHEM (i.e., database) + if (_ctx.Get()->ResultSetGetString(resultSet, "PKTABLE_SCHEM", value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(DATABASE_NAME, *value); + + // PKTABLE_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, 3, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(value); + BOOST_CHECK_EQUAL(table, *value); + + // PKTABLE_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, "PKTABLE_NAME", value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(value); + BOOST_REQUIRE(value->size() > 0); + BOOST_CHECK_EQUAL(table, *value); + + // PKCOLUMN_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, 4, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(value); + BOOST_REQUIRE(value->size() > 0); + BOOST_CHECK_EQUAL(fkColumn, *value); + + // PKCOLUMN_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, "PKCOLUMN_NAME", value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(value); + BOOST_REQUIRE(value->size() > 0); + BOOST_CHECK_EQUAL(fkColumn, *value); + + // FKTABLE_CAT (always null) + if (_ctx.Get()->ResultSetGetString(resultSet, 5, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(!value); + + // FKTABLE_CAT + if (_ctx.Get()->ResultSetGetString(resultSet, "FKTABLE_CAT", value, + errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(!value); + + // FKTABLE_SCHEM (i.e., database) + if (_ctx.Get()->ResultSetGetString(resultSet, 6, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(DATABASE_NAME, *value); + + // FKTABLE_SCHEM (i.e., database) + if (_ctx.Get()->ResultSetGetString(resultSet, "FKTABLE_SCHEM", value, + errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(DATABASE_NAME, *value); + + // FKTABLE_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, 7, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(value); + BOOST_CHECK_EQUAL(fkTableName, *value); + + // FKTABLE_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, "FKTABLE_NAME", value, + errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(value); + BOOST_REQUIRE(value->size() > 0); + BOOST_CHECK_EQUAL(fkTableName, *value); + + // FKCOLUMN_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, 8, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(value); + BOOST_REQUIRE(value->size() > 0); + BOOST_CHECK_EQUAL(fkColumn, *value); + + // FKCOLUMN_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, "FKCOLUMN_NAME", value, + errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(value); + BOOST_REQUIRE(value->size() > 0); + BOOST_CHECK_EQUAL(fkColumn, *value); + + // KEY_SEQ + boost::optional< int > val; + if (_ctx.Get()->ResultSetGetInt(resultSet, 9, val, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(val); + BOOST_CHECK_EQUAL(1, *val); + + // KEY_SEQ + if (_ctx.Get()->ResultSetGetInt(resultSet, "KEY_SEQ", val, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(val); + BOOST_CHECK_EQUAL(1, *val); + + // UPDATE_RULE + if (_ctx.Get()->ResultSetGetInt(resultSet, 10, val, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(val); + + // UPDATE_RULE + if (_ctx.Get()->ResultSetGetInt(resultSet, "UPDATE_RULE", val, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(val); + + // DELETE_RULE + if (_ctx.Get()->ResultSetGetInt(resultSet, 11, val, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(val); + + // DELETE_RULE + if (_ctx.Get()->ResultSetGetInt(resultSet, "DELETE_RULE", val, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(val); + + // FK_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, 12, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(!value); + + // FK_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, "FK_NAME", value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(!value); + + // PK_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, 13, value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(!value); + + // PK_NAME + if (_ctx.Get()->ResultSetGetString(resultSet, "PK_NAME", value, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(!value); + + // DEFERRABILITY + if (_ctx.Get()->ResultSetGetInt(resultSet, 14, val, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(val); + + // DEFERRABILITY + if (_ctx.Get()->ResultSetGetInt(resultSet, "DEFERRABILITY", val, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(val); + + // Get next + if (_ctx.Get()->ResultSetNext(resultSet, hasNext, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + + i++; + } + BOOST_CHECK_EQUAL(2, i); +} + +BOOST_AUTO_TEST_CASE(TestDatabaseMetaDataGetImportedKeysReturnsNone) { + PrepareContext(); + BOOST_REQUIRE(_ctx.Get() != nullptr); + + JniErrorInfo errInfo; + SharedPointer< GlobalJObject > connection; + // get connection + JniErrorCode success = _ctx.Get()->DriverManagerGetConnection( + _jdbcConnectionString.c_str(), connection, errInfo); + if (success != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_REQUIRE(connection.Get()); + AutoCloseConnection autoCloseConnection(_ctx, connection); + + // get databaseMetaData object + SharedPointer< GlobalJObject > databaseMetaData; + if (_ctx.Get()->ConnectionGetMetaData(connection, databaseMetaData, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(databaseMetaData.Get()); + + const boost::optional< std::string > catalog(std::string("")); + const boost::optional< std::string > schema(std::string("")); + std::string fkTableName(""); + SharedPointer< GlobalJObject > resultSet; + if (_ctx.Get()->DatabaseMetaDataGetImportedKeys( + databaseMetaData, catalog, schema, fkTableName, resultSet, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_REQUIRE(resultSet.Get()); + AutoCloseResultSet autoCloseResultSet(_ctx, resultSet); + + bool hasNext; + if (_ctx.Get()->ResultSetNext(resultSet, hasNext, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + std::string errMsg = errInfo.errMsg; + BOOST_FAIL(errMsg); + } + BOOST_CHECK(!hasNext); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/odbc-test/src/jni_test.cpp b/src/odbc-test/src/jni_test.cpp index 739343177..187348df6 100644 --- a/src/odbc-test/src/jni_test.cpp +++ b/src/odbc-test/src/jni_test.cpp @@ -916,6 +916,212 @@ BOOST_AUTO_TEST_CASE(TestDocumentDbDatabaseMetaDataGetColumns) { BOOST_CHECK(!dbConnection.IsOpen()); } +BOOST_AUTO_TEST_CASE(TestDocumentDbDatabaseMetaDataGetImportedKeys) { + PrepareContext(); + BOOST_REQUIRE(_ctx.Get() != nullptr); + + std::string dsnConnectionString; + CreateDsnConnectionStringForLocalServer(dsnConnectionString); + + Configuration config; + ConnectionStringParser parser(config); + parser.ParseConnectionString(dsnConnectionString, nullptr); + JniErrorInfo errInfo; + DocumentDbConnection dbConnection(_ctx); + + BOOST_CHECK(!dbConnection.IsOpen()); + if (dbConnection.Open(config, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_CHECK(dbConnection.IsOpen()); + + SharedPointer< DatabaseMetaData > databaseMetaData = + dbConnection.GetMetaData(errInfo); + BOOST_REQUIRE(databaseMetaData.IsValid()); + + const boost::optional< std::string > fkCatalog = boost::none; + const boost::optional< std::string > fkSchema = boost::none; + std::string fkTable = "jni_test_001_sub_doc"; + SharedPointer< ResultSet > resultSet = + databaseMetaData.Get()->GetImportedKeys(fkCatalog, fkSchema, fkTable, + errInfo); + BOOST_CHECK(resultSet.IsValid()); + BOOST_CHECK(resultSet.Get()->IsOpen()); + + int columnIndex = 0; + // Loop the result set records + bool hasNext = false; + boost::optional< std::string > value; + std::string table = "jni_test_001_sub"; + std::string fkColumn = "jni_test_001_sub__id"; + boost::optional< int16_t > smallIntValue; + do { + resultSet.Get()->Next(hasNext, errInfo); + if (!hasNext) { + break; + } + columnIndex++; + + resultSet.Get()->GetString(1, value, errInfo); + BOOST_CHECK(!value); + + resultSet.Get()->GetString("PKTABLE_CAT", value, errInfo); + BOOST_CHECK(!value); + + resultSet.Get()->GetString(2, value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(DATABASE_NAME, *value); + + resultSet.Get()->GetString("PKTABLE_SCHEM", value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(DATABASE_NAME, *value); + + resultSet.Get()->GetString(3, value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(table, *value); + + resultSet.Get()->GetString("PKTABLE_NAME", value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(table, *value); + + resultSet.Get()->GetString(4, value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK(!value->empty()); + BOOST_CHECK_EQUAL(fkColumn, *value); + + resultSet.Get()->GetString("PKCOLUMN_NAME", value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK(!value->empty()); + BOOST_CHECK_EQUAL(fkColumn, *value); + + resultSet.Get()->GetString(5, value, errInfo); + BOOST_CHECK(!value); + + resultSet.Get()->GetString("FKTABLE_CAT", value, errInfo); + BOOST_CHECK(!value); + + resultSet.Get()->GetString(6, value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(DATABASE_NAME, *value); + + resultSet.Get()->GetString("FKTABLE_SCHEM", value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(DATABASE_NAME, *value); + + resultSet.Get()->GetString(7, value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(fkTable, *value); + + resultSet.Get()->GetString("FKTABLE_NAME", value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK_EQUAL(fkTable, *value); + + resultSet.Get()->GetString(8, value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK(!value->empty()); + BOOST_CHECK_EQUAL(fkColumn, *value); + + resultSet.Get()->GetString("FKCOLUMN_NAME", value, errInfo); + BOOST_CHECK(value); + BOOST_CHECK(!value->empty()); + BOOST_CHECK_EQUAL(fkColumn, *value); + + resultSet.Get()->GetSmallInt(9, smallIntValue, errInfo); + BOOST_CHECK(smallIntValue); + BOOST_CHECK_EQUAL(1, *smallIntValue); + + resultSet.Get()->GetSmallInt("KEY_SEQ", smallIntValue, errInfo); + BOOST_CHECK(smallIntValue); + BOOST_CHECK_EQUAL(1, *smallIntValue); + + resultSet.Get()->GetSmallInt(10, smallIntValue, errInfo); + BOOST_CHECK(smallIntValue); + + resultSet.Get()->GetSmallInt("UPDATE_RULE", smallIntValue, errInfo); + BOOST_CHECK(smallIntValue); + + resultSet.Get()->GetSmallInt(11, smallIntValue, errInfo); + BOOST_CHECK(smallIntValue); + resultSet.Get()->GetSmallInt("DELETE_RULE", smallIntValue, errInfo); + BOOST_CHECK(smallIntValue); + + resultSet.Get()->GetString(12, value, errInfo); + BOOST_CHECK(!value); + resultSet.Get()->GetString("FK_NAME", value, errInfo); + BOOST_CHECK(!value); + + resultSet.Get()->GetString(13, value, errInfo); + BOOST_CHECK(!value); + resultSet.Get()->GetString("PK_NAME", value, errInfo); + BOOST_CHECK(!value); + + resultSet.Get()->GetSmallInt(14, smallIntValue, errInfo); + BOOST_CHECK(smallIntValue); + resultSet.Get()->GetSmallInt("DEFERRABILITY", smallIntValue, errInfo); + BOOST_CHECK(smallIntValue); + } while (hasNext); + BOOST_CHECK_EQUAL(1, columnIndex); + + if (resultSet.Get()->Close(errInfo) != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_CHECK(!resultSet.Get()->IsOpen()); + + if (dbConnection.Close(errInfo) != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_CHECK(!dbConnection.IsOpen()); +} + +BOOST_AUTO_TEST_CASE(TestDocumentDbDatabaseMetaDataGetImportedKeysReturnsNone) { + PrepareContext(); + BOOST_REQUIRE(_ctx.Get() != nullptr); + + std::string dsnConnectionString; + CreateDsnConnectionStringForLocalServer(dsnConnectionString); + + Configuration config; + ConnectionStringParser parser(config); + parser.ParseConnectionString(dsnConnectionString, nullptr); + JniErrorInfo errInfo; + DocumentDbConnection dbConnection(_ctx); + + BOOST_CHECK(!dbConnection.IsOpen()); + if (dbConnection.Open(config, errInfo) + != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_CHECK(dbConnection.IsOpen()); + + SharedPointer< DatabaseMetaData > databaseMetaData = + dbConnection.GetMetaData(errInfo); + BOOST_REQUIRE(databaseMetaData.IsValid()); + + const boost::optional< std::string > fkCatalog(""); + const boost::optional< std::string > fkSchema(""); + std::string fkTable(""); + SharedPointer< ResultSet > resultSet = + databaseMetaData.Get()->GetImportedKeys(fkCatalog, fkSchema, fkTable, + errInfo); + BOOST_CHECK(resultSet.IsValid()); + BOOST_CHECK(resultSet.Get()->IsOpen()); + + bool hasNext = false; + resultSet.Get()->Next(hasNext, errInfo); + BOOST_CHECK(!hasNext); + + if (resultSet.Get()->Close(errInfo) != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_CHECK(!resultSet.Get()->IsOpen()); + + if (dbConnection.Close(errInfo) != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + BOOST_FAIL(errInfo.errMsg); + } + BOOST_CHECK(!dbConnection.IsOpen()); +} + BOOST_AUTO_TEST_CASE(TestDocumentDbGetMqlQueryContext) { PrepareContext(); BOOST_REQUIRE(_ctx.Get() != nullptr); diff --git a/src/odbc-test/src/meta_queries_test.cpp b/src/odbc-test/src/meta_queries_test.cpp index 88f0ad21e..547343fce 100644 --- a/src/odbc-test/src/meta_queries_test.cpp +++ b/src/odbc-test/src/meta_queries_test.cpp @@ -1058,6 +1058,86 @@ BOOST_AUTO_TEST_CASE(TestGetDataWithColumnsReturnsMany) { BOOST_REQUIRE_EQUAL(ret, SQL_NO_DATA); } +BOOST_AUTO_TEST_CASE(TestGetDataWithForeignKeysReturnsOneFromLocalServer) { + SQLCHAR table[] = "meta_queries_test_002_with_array_array"; + + std::string dsnConnectionString; + std::string databaseName("odbc-test"); + CreateDsnConnectionStringForLocalServer(dsnConnectionString, databaseName); + + Connect(dsnConnectionString); + + SQLRETURN ret = + SQLForeignKeys(stmt, NULL, 0, /* Primary catalog */ + NULL, 0, /* Primary schema */ + NULL, 0, /* Primary table */ + NULL, 0, /* Foreign catalog */ + NULL, 0, /* Foreign schema */ + table, sizeof(table)); /* Foreign table */ + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + // check result for PKTableName + CheckSingleRowResultSetWithGetData(stmt, 4, "meta_queries_test_002_with_array__id"); + + SQLCHAR empty[] = ""; + + ret = SQLForeignKeys(stmt, NULL, 0, /* Primary catalog */ + NULL, 0, /* Primary schema */ + NULL, 0, /* Primary table */ + empty, SQL_NTS, /* Foreign catalog */ + NULL, 0, /* Foreign schema */ + table, sizeof(table)); /* Foreign table */ + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + // check result for PKTableName + CheckSingleRowResultSetWithGetData(stmt, 4, + "meta_queries_test_002_with_array__id"); +} + +BOOST_AUTO_TEST_CASE(TestGetDataWithForeignKeysReturnsNone) { + SQLCHAR empty[] = ""; + SQLCHAR table[] = "meta_queries_test_002_with_array_array"; + + std::string dsnConnectionString; + std::string databaseName("odbc-test"); + CreateDsnConnectionStringForLocalServer(dsnConnectionString, databaseName); + + Connect(dsnConnectionString); + + SQLRETURN ret = SQLForeignKeys(stmt, empty, SQL_NTS, /* Primary catalog */ + empty, SQL_NTS, /* Primary schema */ + empty, SQL_NTS, /* Primary table */ + empty, SQL_NTS, /* Foreign catalog */ + empty, SQL_NTS, /* Foreign schema */ + empty, SQL_NTS); /* Foreign table */ + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLFetch(stmt); + + BOOST_REQUIRE_EQUAL(ret, SQL_NO_DATA); + + // when empty strings are passed as catalog/schema, SQL_NO_DATA should be returned + ret = SQLForeignKeys(stmt, empty, SQL_NTS, /* Primary catalog */ + empty, SQL_NTS, /* Primary schema */ + empty, SQL_NTS, /* Primary table */ + empty, SQL_NTS, /* Foreign catalog */ + empty, SQL_NTS, /* Foreign schema */ + table, sizeof(table)); /* Foreign table */ + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLFetch(stmt); + + BOOST_REQUIRE_EQUAL(ret, SQL_NO_DATA); +} + BOOST_AUTO_TEST_CASE(TestSQLColumnWithSQLBindCols) { std::string dsnConnectionString; CreateDsnConnectionStringForLocalServer(dsnConnectionString); diff --git a/src/odbc/CMakeLists.txt b/src/odbc/CMakeLists.txt index 695dfea53..137d54032 100644 --- a/src/odbc/CMakeLists.txt +++ b/src/odbc/CMakeLists.txt @@ -84,6 +84,7 @@ set(SOURCES src/app/application_data_buffer.cpp src/jni/result_set.cpp src/environment.cpp src/meta/column_meta.cpp + src/meta/foreign_key_meta.cpp src/meta/table_meta.cpp src/odbc.cpp src/entry_points.cpp diff --git a/src/odbc/include/ignite/odbc.h b/src/odbc/include/ignite/odbc.h index fa0f174dc..619c2691b 100644 --- a/src/odbc/include/ignite/odbc.h +++ b/src/odbc/include/ignite/odbc.h @@ -126,6 +126,12 @@ SQLRETURN SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT columnNum, SQLRETURN SQLRowCount(SQLHSTMT stmt, SQLLEN* rowCnt); +/** Currently, we only support the following case : + * If *FKTableName contains a table name, SQLForeignKeys returns a result set + * that contains all the foreign keys in the specified table that point to + * primary keys in other tables, and the primary keys in the other tables to + * which they refer. The list of foreign keys in the specified table does not + * contain foreign keys that refer to unique constraints in other tables. */ SQLRETURN SQLForeignKeys( SQLHSTMT stmt, SQLCHAR* primaryCatalogName, SQLSMALLINT primaryCatalogNameLen, SQLCHAR* primarySchemaName, diff --git a/src/odbc/include/ignite/odbc/jni/database_metadata.h b/src/odbc/include/ignite/odbc/jni/database_metadata.h index 3cbe66329..b8c3e5427 100644 --- a/src/odbc/include/ignite/odbc/jni/database_metadata.h +++ b/src/odbc/include/ignite/odbc/jni/database_metadata.h @@ -65,6 +65,16 @@ class DatabaseMetaData { const std::string& columnNamePattern, JniErrorInfo& errInfo); + /** + * Query the foreign keys in the database according to the given + * search critera in catalog (not supported), schema, and + * table. + */ + SharedPointer< ResultSet > GetImportedKeys(const boost::optional< std::string >& catalog, + const boost::optional< std::string >& schema, + const std::string& table, + JniErrorInfo& errInfo); + private: /** * Constructs an instance of the DatabaseMetaData class. diff --git a/src/odbc/include/ignite/odbc/jni/java.h b/src/odbc/include/ignite/odbc/jni/java.h index 6c9a519b1..9d36dc497 100644 --- a/src/odbc/include/ignite/odbc/jni/java.h +++ b/src/odbc/include/ignite/odbc/jni/java.h @@ -288,6 +288,7 @@ struct JniMembers { jclass c_DatabaseMetaData; jmethodID m_DatabaseMetaDataGetTables; jmethodID m_DatabaseMetaDataGetColumns; + jmethodID m_DatabaseMetaDataGetImportedKeys; jclass c_List; jmethodID m_ListSize; @@ -529,6 +530,13 @@ class IGNITE_IMPORT_EXPORT JniContext { const std::string& tableNamePattern, const std::string& columnNamePattern, SharedPointer< GlobalJObject >& resultSet, JniErrorInfo& errInfo); + JniErrorCode DatabaseMetaDataGetImportedKeys( + const SharedPointer< GlobalJObject >& databaseMetaData, + const boost::optional< std::string >& catalog, + const boost::optional< std::string >& schema, + const std::string& table, SharedPointer< GlobalJObject >& resultSet, + JniErrorInfo& errInfo); + JniErrorCode ResultSetClose(const SharedPointer< GlobalJObject >& resultSet, JniErrorInfo& errInfo); JniErrorCode ResultSetNext(const SharedPointer< GlobalJObject >& resultSet, diff --git a/src/odbc/include/ignite/odbc/jni/result_set.h b/src/odbc/include/ignite/odbc/jni/result_set.h index fe156261a..668167105 100644 --- a/src/odbc/include/ignite/odbc/jni/result_set.h +++ b/src/odbc/include/ignite/odbc/jni/result_set.h @@ -114,6 +114,28 @@ class ResultSet { JniErrorCode GetInt(const std::string& columnName, boost::optional< int >& value, JniErrorInfo& errInfo); + /** + * Gets a value on the current row of the result set for the + * given columnIndex (1-indexed). If a value exists, the value + * is set. If the value is null, the wasNull will be set to + * true, false, otherwise. + * + * @return a JniErrorCode indicating success or failure. + */ + JniErrorCode GetSmallInt(const int columnIndex, + boost::optional< int16_t >& value, + JniErrorInfo& errInfo); + /** + * Gets a value on the current row of the result set for the + * given columnName. If a value exists, the value + * is set. If the value is null, the wasNull will be set to + * true, false, otherwise. + * + * @return a JniErrorCode indicating success or failure. + */ + JniErrorCode GetSmallInt(const std::string& columnName, + boost::optional< int16_t >& value, + JniErrorInfo& errInfo); private: /** * Constructs a new instancee of ResultSet. diff --git a/src/odbc/include/ignite/odbc/meta/foreign_key_meta.h b/src/odbc/include/ignite/odbc/meta/foreign_key_meta.h new file mode 100644 index 000000000..405bae7ff --- /dev/null +++ b/src/odbc/include/ignite/odbc/meta/foreign_key_meta.h @@ -0,0 +1,318 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _IGNITE_ODBC_META_FOREIGN_KEY_META +#define _IGNITE_ODBC_META_FOREIGN_KEY_META + +#include + +#include +#include +#include + +#include "ignite/odbc/impl/binary/binary_reader_impl.h" +#include "ignite/odbc/utility.h" +#include "ignite/odbc/jni/result_set.h" + +using ignite::odbc::jni::ResultSet; + +namespace ignite { +namespace odbc { +namespace meta { +/** + * Foreign key metadata. + */ +class ForeignKeyMeta { + public: + /** + * Default constructor. + */ + ForeignKeyMeta() : keySeq(0) { + // No-op. + } + + /** + * Constructor. + * + * @param PKCatalogName Primary key table catalog name + * @param PKSchemaName Primary key table schema name. + * @param PKTableName Primary key table name. + * @param PKColumnName Primary key column name. + * @param FKCatalogName Foreign key table catalog name + * @param FKSchemaName Foreign key table schema name. + * @param FKTableName Foreign key table name. + * @param FKColumnName Foreign key column name. + * @param keySeq Column sequence number in key (starting with 1). + * @param updateRule Update rule. + * @param deleteRule Delete rule. + * @param PKName Primary key name. + * @param FKName Foreign key name. + * @param deferrability Deferrability. + */ + ForeignKeyMeta( + const std::string& PKCatalogName, const std::string& PKSchemaName, + const std::string& PKTableName, const std::string& PKColumnName, + const std::string& FKCatalogName, const std::string& FKSchemaName, + const std::string& FKTableName, const std::string& FKColumnName, + int16_t keySeq, int16_t updateRule, int16_t deleteRule, + const std::string& PKName, const std::string& FKName, + int16_t deferrability) + : PKCatalogName(PKCatalogName), + PKSchemaName(PKSchemaName), + PKTableName(PKTableName), + PKColumnName(PKColumnName), + FKCatalogName(FKCatalogName), + FKSchemaName(FKSchemaName), + FKTableName(FKTableName), + FKColumnName(FKColumnName), + keySeq(keySeq), + updateRule(updateRule), + deleteRule(deleteRule), + PKName(PKName), + FKName(FKName), + deferrability(deferrability) { + // No-op. + } + + /** + * Destructor. + */ + ~ForeignKeyMeta() { + // No-op. + } + + /** + * Copy constructor. + */ + ForeignKeyMeta(const ForeignKeyMeta& other) + : PKCatalogName(other.PKCatalogName), + PKSchemaName(other.PKSchemaName), + PKTableName(other.PKTableName), + PKColumnName(other.PKColumnName), + FKCatalogName(other.FKCatalogName), + FKSchemaName(other.FKSchemaName), + FKTableName(other.FKTableName), + FKColumnName(other.FKColumnName), + keySeq(other.keySeq), + updateRule(other.updateRule), + deleteRule(other.deleteRule), + PKName(other.PKName), + FKName(other.FKName), + deferrability(other.deferrability) { + // No-op. + } + + /** + * Copy operator. + */ + ForeignKeyMeta& operator=(const ForeignKeyMeta& other) { + PKCatalogName = other.PKCatalogName; + PKSchemaName = other.PKSchemaName; + PKTableName = other.PKTableName; + PKColumnName = other.PKColumnName; + FKCatalogName = other.FKCatalogName; + FKSchemaName = other.FKSchemaName; + FKTableName = other.FKTableName; + FKColumnName = other.FKColumnName; + keySeq = other.keySeq; + updateRule = other.updateRule; + deleteRule = other.deleteRule; + PKName = other.PKName; + FKName = other.FKName; + deferrability = other.deferrability; + + return *this; + } + + /** + * Read resultset item. + * @param resultSet SharedPointer< ResultSet >. + * @paran errInfo JniErrorInfo. + */ + void Read(SharedPointer< ResultSet >& resultSet, JniErrorInfo& errInfo); + + /** + * Get primary key table catalog name. + * @return Primary key table catalog name. + */ + const boost::optional< std::string >& GetPKCatalogName() const { + return PKCatalogName; + } + + /** + * Get primary key table schema name. + * @return Primary key table schema name. + */ + const boost::optional< std::string >& GetPKSchemaName() const { + return PKSchemaName; + } + + /** + * Get primary key table name. + * @return Primary key table name. + */ + const boost::optional< std::string >& GetPKTableName() const { + return PKTableName; + } + + /** + * Get foreign key column name. + * @return Primary key column name. + */ + const boost::optional< std::string >& GetPKColumnName() const { + return PKColumnName; + } + + /** + * Get foreign key table catalog name. + * @return Foreign key table catalog name. + */ + const boost::optional< std::string >& GetFKCatalogName() const { + return FKCatalogName; + } + + /** + * Get foreign key table schema name. + * @return Foreign key table schema name. + */ + const boost::optional< std::string >& GetFKSchemaName() const { + return FKSchemaName; + } + + /** + * Get foreign key table name. + * @return Foreign key table name. + */ + const boost::optional< std::string >& GetFKTableName() const { + return FKTableName; + } + + /** + * Get foreign key column name. + * @return Foreign key column name. + */ + const boost::optional< std::string >& GetFKColumnName() const { + return FKColumnName; + } + + /** + * Get column sequence number in key. + * @return Sequence number in key. + */ + boost::optional< int16_t > GetKeySeq() const { + return keySeq; + } + + /** + * Get update rule. + * @return Update rule. + */ + boost::optional< int16_t > GetUpdateRule() const { + return updateRule; + } + + /** + * Get delete rule. + * @return Delete rule. + */ + boost::optional< int16_t > GetDeleteRule() const { + return deleteRule; + } + + /** + * Get foreign key name. + * @return Foreign Key name. + */ + const boost::optional< std::string >& GetFKName() const { + return FKName; + } + + /** + * Get primary key name. + * @return Primary Key name. + */ + const boost::optional< std::string >& GetPKName() const { + return PKName; + } + + /** + * Get deferrability. + * @return Deferrability. + */ + boost::optional< int16_t > GetDeferrability() const { + return deferrability; + } + + private: + /** Primary key table catalog name. */ + boost::optional< std::string > PKCatalogName; + + /** Primary key table schema name. */ + boost::optional< std::string > PKSchemaName; + + /** Primary key table name. */ + boost::optional< std::string > PKTableName; + + /** Primary key column name. */ + boost::optional< std::string > PKColumnName; + + /** Foreign key table catalog name. */ + boost::optional< std::string > FKCatalogName; + + /** Foreign key table schema name. */ + boost::optional< std::string > FKSchemaName; + + /** Foreign key table name. */ + boost::optional< std::string > FKTableName; + + /** Foreign key column name. */ + boost::optional< std::string > FKColumnName; + + /** Column sequence number in key. */ + boost::optional< int16_t > keySeq; + + /** Update rule. */ + boost::optional< int16_t > updateRule; + + /** Delete rule. */ + boost::optional< int16_t > deleteRule; + + /** Foreign key name. */ + boost::optional< std::string > FKName; + + /** Primary key name. */ + boost::optional< std::string > PKName; + + /** Deferrability. */ + boost::optional< int16_t > deferrability; +}; + +/** Table metadata vector alias. */ +typedef std::vector< ForeignKeyMeta > ForeignKeyMetaVector; + +/** + * Read foreign keys metadata collection. + * @param resultSet SharedPointer< ResultSet >. + * @param meta Collection. + */ +void ReadForeignKeysColumnMetaVector(SharedPointer< ResultSet >& resultSet, + ForeignKeyMetaVector& meta); +} // namespace meta +} // namespace odbc +} // namespace ignite + +#endif //_IGNITE_ODBC_META_FOREIGN_KEY_META diff --git a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h index dcceb01f3..978902412 100644 --- a/src/odbc/include/ignite/odbc/meta/primary_key_meta.h +++ b/src/odbc/include/ignite/odbc/meta/primary_key_meta.h @@ -154,7 +154,7 @@ class PrimaryKeyMeta { /** Table name. */ std::string table; - /** Collumn name. */ + /** Column name. */ std::string column; /** Column sequence number in key. */ diff --git a/src/odbc/include/ignite/odbc/query/foreign_keys_query.h b/src/odbc/include/ignite/odbc/query/foreign_keys_query.h index 63e7733f7..718a2f7c1 100644 --- a/src/odbc/include/ignite/odbc/query/foreign_keys_query.h +++ b/src/odbc/include/ignite/odbc/query/foreign_keys_query.h @@ -20,6 +20,7 @@ #include "ignite/odbc/connection.h" #include "ignite/odbc/query/query.h" +#include "ignite/odbc/meta/foreign_key_meta.h" namespace ignite { namespace odbc { @@ -29,25 +30,20 @@ namespace query { */ class ForeignKeysQuery : public Query { public: + /** * Constructor. * * @param diag Diagnostics collector. * @param connection Statement-associated connection. - * @param primaryCatalog Primary key catalog name. - * @param primarySchema Primary key schema name. - * @param primaryTable Primary key table name. - * @param foreignCatalog Foreign key catalog name. - * @param foreignSchema Foreign key schema name. - * @param foreignTable Foreign key table name. + * @param catalog Foreign key catalog name. + * @param schema Foreign key schema name. + * @param table Foreign key table name. */ ForeignKeysQuery(diagnostic::DiagnosableAdapter& diag, Connection& connection, - const std::string& primaryCatalog, - const std::string& primarySchema, - const std::string& primaryTable, - const std::string& foreignCatalog, - const std::string& foreignSchema, - const std::string& foreignTable); + const boost::optional< std::string >& catalog, + const boost::optional< std::string >& schema, + const std::string& table); /** * Destructor. @@ -116,32 +112,40 @@ class ForeignKeysQuery : public Query { private: IGNITE_NO_COPY_ASSIGNMENT(ForeignKeysQuery); + /** + * Make get foreign keys metadata requets and use response to set internal + * state. + * + * @return Operation result. + */ + virtual SqlResult::Type MakeRequestGetForeignKeysMeta(); + /** Connection associated with the statement. */ Connection& connection; - /** Primary key catalog name. */ - std::string primaryCatalog; - - /** Primary key schema name. */ - std::string primarySchema; - - /** Primary key table name. */ - std::string primaryTable; - /** Foreign key catalog name. */ - std::string foreignCatalog; + const boost::optional< std::string > catalog; /** Foreign key schema name. */ - std::string foreignSchema; + const boost::optional< std::string > schema; /** Foreign key table name. */ - std::string foreignTable; + std::string table; /** Query executed. */ bool executed; + /** Fetched flag. */ + bool fetched; + /** Columns metadata. */ meta::ColumnMetaVector columnsMeta; + + /** Metadata cursor. */ + meta::ForeignKeyMetaVector::iterator cursor; + + /** Fetched Foreign Keys metadata. */ + meta::ForeignKeyMetaVector meta; }; } // namespace query } // namespace odbc diff --git a/src/odbc/include/ignite/odbc/statement.h b/src/odbc/include/ignite/odbc/statement.h index fa52908a8..197da30cb 100644 --- a/src/odbc/include/ignite/odbc/statement.h +++ b/src/odbc/include/ignite/odbc/statement.h @@ -200,8 +200,8 @@ class Statement : public diagnostic::DiagnosableAdapter { void ExecuteGetForeignKeysQuery(const std::string& primaryCatalog, const std::string& primarySchema, const std::string& primaryTable, - const std::string& foreignCatalog, - const std::string& foreignSchema, + const boost::optional< std::string >& foreignCatalog, + const boost::optional< std::string >& foreignSchema, const std::string& foreignTable); /** @@ -558,6 +558,7 @@ class Statement : public diagnostic::DiagnosableAdapter { /** * Get foreign keys. + * Params for primary key catalog, schema, and table names are ignored. * * @param primaryCatalog Primary key catalog name. * @param primarySchema Primary key schema name. @@ -569,8 +570,10 @@ class Statement : public diagnostic::DiagnosableAdapter { */ SqlResult::Type InternalExecuteGetForeignKeysQuery( const std::string& primaryCatalog, const std::string& primarySchema, - const std::string& primaryTable, const std::string& foreignCatalog, - const std::string& foreignSchema, const std::string& foreignTable); + const std::string& primaryTable, + const boost::optional< std::string >& foreignCatalog, + const boost::optional< std::string >& foreignSchema, + const std::string& foreignTable); /** * Get primary keys. diff --git a/src/odbc/include/ignite/odbc/utility.h b/src/odbc/include/ignite/odbc/utility.h index 1e4bdf8ce..771cdc97f 100644 --- a/src/odbc/include/ignite/odbc/utility.h +++ b/src/odbc/include/ignite/odbc/utility.h @@ -26,6 +26,8 @@ #include #include +#include +#include #include #include "ignite/odbc/impl/binary/binary_reader_impl.h" @@ -106,6 +108,17 @@ void WriteDecimal(BinaryWriterImpl& writer, */ std::string SqlStringToString(const unsigned char* sqlStr, int32_t sqlStrLen); +/** + * Convert SQL string buffer to boost::optional< std::string >. + * + * @param sqlStr SQL string buffer. + * @param sqlStrLen SQL string length. + * @return Standard optional string containing the same data. + * If sqlStrLen indicates null string, boost::none is returned. + */ +boost::optional< std::string > SqlStringToOptString(const unsigned char* sqlStr, + int32_t sqlStrLen); + /** * Convert binary data to hex dump form * @param data pointer to data diff --git a/src/odbc/src/jni/database_metadata.cpp b/src/odbc/src/jni/database_metadata.cpp index 2fd2fb90a..942b3be46 100644 --- a/src/odbc/src/jni/database_metadata.cpp +++ b/src/odbc/src/jni/database_metadata.cpp @@ -58,6 +58,20 @@ SharedPointer< ResultSet > DatabaseMetaData::GetColumns( } return new ResultSet(_jniContext, resultSet); } + +SharedPointer< ResultSet > DatabaseMetaData::GetImportedKeys( + const boost::optional< std::string >& catalog, + const boost::optional< std::string >& schema, + const std::string& table, JniErrorInfo& errInfo) { + SharedPointer< GlobalJObject > resultSet; + const std::vector< std::string > types; + JniErrorCode success = _jniContext.Get()->DatabaseMetaDataGetImportedKeys( + _databaseMetaData, catalog, schema, table, resultSet, errInfo); + if (success != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + return nullptr; + } + return new ResultSet(_jniContext, resultSet); +} } // namespace jni } // namespace odbc } // namespace ignite diff --git a/src/odbc/src/jni/java.cpp b/src/odbc/src/jni/java.cpp index e33dba231..eb4f643b0 100644 --- a/src/odbc/src/jni/java.cpp +++ b/src/odbc/src/jni/java.cpp @@ -257,6 +257,10 @@ JniMethod const M_DATABASE_META_DATA_GET_COLUMNS = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" "String;Ljava/lang/String;)Ljava/sql/ResultSet;", false); +JniMethod const M_DATABASE_META_DATA_GET_IMPORTED_KEYS = + JniMethod("getImportedKeys", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/" + "String;)Ljava/sql/ResultSet;", false); const char* const C_DOCUMENTDB_CONNECTION = "software/amazon/documentdb/jdbc/DocumentDbConnection"; @@ -660,6 +664,8 @@ void JniMembers::Initialize(JNIEnv* env) { FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_TABLES); m_DatabaseMetaDataGetColumns = FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_COLUMNS); + m_DatabaseMetaDataGetImportedKeys = + FindMethod(env, c_DatabaseMetaData, M_DATABASE_META_DATA_GET_IMPORTED_KEYS); c_Connection = FindClass(env, C_JAVA_SQL_CONNECTION); m_ConnectionClose = @@ -1414,6 +1420,54 @@ JniErrorCode JniContext::DatabaseMetaDataGetColumns( return errInfo.code; } +JniErrorCode JniContext::DatabaseMetaDataGetImportedKeys( + const SharedPointer< GlobalJObject >& databaseMetaData, + const boost::optional< std::string >& catalog, + const boost::optional< std::string >& schema, + const std::string& table, SharedPointer< GlobalJObject >& resultSet, + JniErrorInfo& errInfo) { + LOG_DEBUG_MSG("DatabaseMetaDataGetImportedKeys is called"); + + if (databaseMetaData.Get() == nullptr) { + errInfo.code = JniErrorCode::IGNITE_JNI_ERR_GENERIC; + errInfo.errMsg = "DatabaseMetaData object must be set."; + + LOG_ERROR_MSG("DatabaseMetaDataGetImportedKeys exiting with error msg: " + << errInfo.errMsg); + + return errInfo.code; + } + + JNIEnv* env = Attach(); + jstring jCatalog = catalog ? env->NewStringUTF(catalog->c_str()) : nullptr; + jstring jSchema = schema ? env->NewStringUTF(schema->c_str()) : nullptr; + jstring jTable = env->NewStringUTF(table.c_str()); + + jobject result = env->CallObjectMethod( + databaseMetaData.Get()->GetRef(), + jvm->GetMembers().m_DatabaseMetaDataGetImportedKeys, jCatalog, jSchema, + jTable); + ExceptionCheck(env, &errInfo); + + env->DeleteLocalRef(jCatalog); + env->DeleteLocalRef(jSchema); + env->DeleteLocalRef(jTable); + + if (!result || errInfo.code != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + resultSet = nullptr; + LOG_ERROR_MSG( + "DatabaseMetaDataGetImportedKeys exiting with error. resultSet will be " + "null"); + return errInfo.code; + } + + resultSet = new GlobalJObject(env, env->NewGlobalRef(result)); + + LOG_DEBUG_MSG("DatabaseMetaDataGetImportedKeys exiting"); + + return errInfo.code; +} + JniErrorCode JniContext::ResultSetClose( const SharedPointer< GlobalJObject >& resultSet, JniErrorInfo& errInfo) { LOG_DEBUG_MSG("ResultSetClose is called"); diff --git a/src/odbc/src/jni/result_set.cpp b/src/odbc/src/jni/result_set.cpp index 20999cc5e..03a3c3463 100644 --- a/src/odbc/src/jni/result_set.cpp +++ b/src/odbc/src/jni/result_set.cpp @@ -85,6 +85,28 @@ JniErrorCode ResultSet::GetInt(const std::string& columnName, return _jniContext.Get()->ResultSetGetInt(_resultSet, columnName, value, errInfo); } + +JniErrorCode ResultSet::GetSmallInt(const int columnIndex, + boost::optional< int16_t >& value, + JniErrorInfo& errInfo) { + boost::optional< int > val; + JniErrorCode err = + _jniContext.Get()->ResultSetGetInt(_resultSet, columnIndex, val, errInfo); + if (val) + value = static_cast< int16_t >(*val); + return err; +} + +JniErrorCode ResultSet::GetSmallInt(const std::string& columnName, + boost::optional< int16_t >& value, + JniErrorInfo& errInfo) { + boost::optional< int > val; + JniErrorCode err = + _jniContext.Get()->ResultSetGetInt(_resultSet, columnName, val, errInfo); + if (val) + value = static_cast< int16_t >(*val); + return err; +} } // namespace jni } // namespace odbc } // namespace ignite diff --git a/src/odbc/src/meta/column_meta.cpp b/src/odbc/src/meta/column_meta.cpp index b0905bdf4..69db09949 100644 --- a/src/odbc/src/meta/column_meta.cpp +++ b/src/odbc/src/meta/column_meta.cpp @@ -108,14 +108,11 @@ const std::string ORDINAL_POSITION = "ORDINAL_POSITION"; void ColumnMeta::Read(SharedPointer< ResultSet >& resultSet, int32_t& prevPosition, JniErrorInfo& errInfo) { - boost::optional< int > intDataType; resultSet.Get()->GetString(TABLE_CAT, catalogName, errInfo); resultSet.Get()->GetString(TABLE_SCHEM, schemaName, errInfo); resultSet.Get()->GetString(TABLE_NAME, tableName, errInfo); resultSet.Get()->GetString(COLUMN_NAME, columnName, errInfo); - resultSet.Get()->GetInt(DATA_TYPE, intDataType, errInfo); - if (intDataType) - dataType = static_cast< int16_t >(*intDataType); + resultSet.Get()->GetSmallInt(DATA_TYPE, dataType, errInfo); resultSet.Get()->GetString(REMARKS, remarks, errInfo); resultSet.Get()->GetString(COLUMN_DEF, columnDef, errInfo); resultSet.Get()->GetInt(NULLABLE, nullability, errInfo); diff --git a/src/odbc/src/meta/foreign_key_meta.cpp b/src/odbc/src/meta/foreign_key_meta.cpp new file mode 100644 index 000000000..b2d71a376 --- /dev/null +++ b/src/odbc/src/meta/foreign_key_meta.cpp @@ -0,0 +1,89 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ignite/odbc/meta/foreign_key_meta.h" + +#include "ignite/odbc/impl/binary/binary_common.h" +#include "ignite/odbc/common/utils.h" +#include "ignite/odbc/common_types.h" +#include "ignite/odbc/jni/java.h" +#include "ignite/odbc/log.h" +#include "ignite/odbc/system/odbc_constants.h" +#include "ignite/odbc/type_traits.h" + +namespace ignite { +namespace odbc { +namespace meta { +const std::string PKTABLE_CAT = "PKTABLE_CAT"; +const std::string PKTABLE_SCHEM = "PKTABLE_SCHEM"; +const std::string PKTABLE_NAME = "PKTABLE_NAME"; +const std::string PKCOLUMN_NAME = "PKCOLUMN_NAME"; +const std::string FKTABLE_CAT = "FKTABLE_CAT"; +const std::string FKTABLE_SCHEM = "FKTABLE_SCHEM"; +const std::string FKTABLE_NAME = "FKTABLE_NAME"; +const std::string FKCOLUMN_NAME = "FKCOLUMN_NAME"; +const std::string KEY_SEQ = "KEY_SEQ"; +const std::string UPDATE_RULE = "UPDATE_RULE"; +const std::string DELETE_RULE = "DELETE_RULE"; +const std::string FK_NAME = "FK_NAME"; +const std::string PK_NAME = "PK_NAME"; +const std::string DEFERRABILITY = "DEFERRABILITY"; + +void ForeignKeyMeta::Read(SharedPointer< ResultSet >& resultSet, JniErrorInfo& errInfo) { + boost::optional< int > intDataType; + resultSet.Get()->GetString(PKTABLE_CAT, PKCatalogName, errInfo); + resultSet.Get()->GetString(PKTABLE_SCHEM, PKSchemaName, errInfo); + resultSet.Get()->GetString(PKTABLE_NAME, PKTableName, errInfo); + resultSet.Get()->GetString(PKCOLUMN_NAME, PKColumnName, errInfo); + resultSet.Get()->GetString(FKTABLE_CAT, FKCatalogName, errInfo); + resultSet.Get()->GetString(FKTABLE_SCHEM, FKSchemaName, errInfo); + resultSet.Get()->GetString(FKTABLE_NAME, FKTableName, errInfo); + resultSet.Get()->GetString(FKCOLUMN_NAME, FKColumnName, errInfo); + resultSet.Get()->GetSmallInt(KEY_SEQ, keySeq, errInfo); + resultSet.Get()->GetSmallInt(UPDATE_RULE, updateRule, errInfo); + resultSet.Get()->GetSmallInt(DELETE_RULE, deleteRule, errInfo); + resultSet.Get()->GetString(FK_NAME, FKName, errInfo); + resultSet.Get()->GetString(PK_NAME, PKName, errInfo); + resultSet.Get()->GetSmallInt(DEFERRABILITY, deferrability, errInfo); +} + +void ReadForeignKeysColumnMetaVector(SharedPointer< ResultSet >& resultSet, + ForeignKeyMetaVector& meta) { + meta.clear(); + + if (!resultSet.IsValid()) { + return; + } + + JniErrorInfo errInfo; + bool hasNext = false; + int32_t prevPosition = 0; + JniErrorCode errCode; + do { + errCode = resultSet.Get()->Next(hasNext, errInfo); + if (!hasNext || errCode != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + break; + } + + meta.emplace_back(ForeignKeyMeta()); + meta.back().Read(resultSet, errInfo); + } while (hasNext); +} + +} // namespace meta +} // namespace odbc +} // namespace ignite diff --git a/src/odbc/src/odbc.cpp b/src/odbc/src/odbc.cpp index a5ea78bd3..673e3b16f 100644 --- a/src/odbc/src/odbc.cpp +++ b/src/odbc/src/odbc.cpp @@ -326,11 +326,11 @@ SQLRETURN SQLDriverConnect(SQLHDBC conn, SQLHWND windowHandle, LOG_DEBUG_MSG("SQLDriverConnect called"); - // TODO enable logging connection string + // TODO enable logging connection string // https://bitquill.atlassian.net/browse/AD-702 - - //if (inConnectionString) - // LOG_INFO_MSG("Connection String: [" << inConnectionString << "]"); + + // if (inConnectionString) + // LOG_INFO_MSG("Connection String: [" << inConnectionString << "]"); Connection* connection = reinterpret_cast< Connection* >(conn); @@ -360,8 +360,8 @@ SQLRETURN SQLDriverConnect(SQLHDBC conn, SQLHWND windowHandle, if (outConnectionStringLen) *outConnectionStringLen = static_cast< SQLSMALLINT >(reslen); - //if (outConnectionString) - // LOG_INFO_MSG(outConnectionString); + // if (outConnectionString) + // LOG_INFO_MSG(outConnectionString); LOG_DEBUG_MSG("SQLDriverConnect exiting"); @@ -852,9 +852,10 @@ SQLRETURN SQLDescribeCol(SQLHSTMT stmt, SQLUSMALLINT columnNum, LOG_INFO_MSG("columnSizeRes: " << columnSizeRes); LOG_INFO_MSG("decimalDigitsRes: " << decimalDigitsRes); LOG_INFO_MSG("nullableRes: " << nullableRes); - LOG_INFO_MSG("columnNameBuf: " - << (columnNameBuf ? reinterpret_cast< const char* >(columnNameBuf) - : "")); + LOG_INFO_MSG( + "columnNameBuf: " << (columnNameBuf + ? reinterpret_cast< const char* >(columnNameBuf) + : "")); LOG_INFO_MSG("columnNameLen: " << (columnNameLen ? *columnNameLen : -1)); if (dataType) @@ -910,6 +911,7 @@ SQLRETURN SQLForeignKeys( SQLSMALLINT foreignTableNameLen) { using odbc::Statement; using odbc::utility::SqlStringToString; + using odbc::utility::SqlStringToOptString; LOG_DEBUG_MSG("SQLForeignKeys called"); @@ -928,18 +930,18 @@ SQLRETURN SQLForeignKeys( SqlStringToString(primarySchemaName, primarySchemaNameLen); std::string primaryTable = SqlStringToString(primaryTableName, primaryTableNameLen); - std::string foreignCatalog = - SqlStringToString(foreignCatalogName, foreignCatalogNameLen); - std::string foreignSchema = - SqlStringToString(foreignSchemaName, foreignSchemaNameLen); + const boost::optional< std::string > foreignCatalog = + SqlStringToOptString(foreignCatalogName, foreignCatalogNameLen); + const boost::optional< std::string > foreignSchema = + SqlStringToOptString(foreignSchemaName, foreignSchemaNameLen); std::string foreignTable = SqlStringToString(foreignTableName, foreignTableNameLen); LOG_INFO_MSG("primaryCatalog: " << primaryCatalog); LOG_INFO_MSG("primarySchema: " << primarySchema); LOG_INFO_MSG("primaryTable: " << primaryTable); - LOG_INFO_MSG("foreignCatalog: " << foreignCatalog); - LOG_INFO_MSG("foreignSchema: " << foreignSchema); + LOG_INFO_MSG("foreignCatalog: " << foreignCatalog.get_value_or("")); + LOG_INFO_MSG("foreignSchema: " << foreignSchema.get_value_or("")); LOG_INFO_MSG("foreignTable: " << foreignTable); statement->ExecuteGetForeignKeysQuery(primaryCatalog, primarySchema, @@ -1167,7 +1169,8 @@ SQLRETURN SQLGetDiagRec(SQLSMALLINT handleType, SQLHANDLE handle, } else { LOG_ERROR_MSG( "SQLGetDiagRec exiting with SQL_NO_DATA because records variable is " - "null. recNum: " << recNum << ", records: " << records); + "null. recNum: " + << recNum << ", records: " << records); } return SQL_NO_DATA; } diff --git a/src/odbc/src/query/column_metadata_query.cpp b/src/odbc/src/query/column_metadata_query.cpp index ede19da59..4fdb3487f 100644 --- a/src/odbc/src/query/column_metadata_query.cpp +++ b/src/odbc/src/query/column_metadata_query.cpp @@ -125,8 +125,8 @@ ColumnMetadataQuery::ColumnMetadataQuery(diagnostic::DiagnosableAdapter& diag, columnsMeta.reserve(18); - const std::string sch; - const std::string tbl; + const std::string sch(""); + const std::string tbl(""); columnsMeta.push_back(ColumnMeta(sch, tbl, "TABLE_CAT", JDBC_TYPE_VARCHAR, Nullability::NULLABLE)); diff --git a/src/odbc/src/query/foreign_keys_query.cpp b/src/odbc/src/query/foreign_keys_query.cpp index 3972bd382..0c95bd2ce 100644 --- a/src/odbc/src/query/foreign_keys_query.cpp +++ b/src/odbc/src/query/foreign_keys_query.cpp @@ -17,27 +17,79 @@ #include "ignite/odbc/query/foreign_keys_query.h" -#include "ignite/odbc/impl/binary/binary_common.h" #include "ignite/odbc/connection.h" +#include "ignite/odbc/impl/binary/binary_common.h" +#include "ignite/odbc/log.h" #include "ignite/odbc/message.h" #include "ignite/odbc/type_traits.h" +namespace { +struct ResultColumn { + enum Type { + /** Primary key table catalog being imported. NULL if not applicable to the + data source. */ + PKTABLE_CAT = 1, + + /** Primary key table schema being imported. NULL if not applicable to the + data source. */ + PKTABLE_SCHEM, + + /** Primary key table name being imported. */ + PKTABLE_NAME, + + /** Primary key column name being imported. */ + PKCOLUMN_NAME, + + /** Foreign key table catalog being imported. NULL if not applicable to the + data source. */ + FKTABLE_CAT, + + /** Foreign key table schema being imported. NULL if not applicable to the + data source. */ + FKTABLE_SCHEM, + + /** Foreign key table name being imported. */ + FKTABLE_NAME, + + /** Foreign key column name being imported. */ + FKCOLUMN_NAME, + + /** Sequence number within a foreign key + * (a value of 1 represents the first column of the foreign key, a value of + * 2 would represent the second column within the foreign key). */ + KEY_SEQ, + + /** Rule for updating a foreign key when the primary key is updated. */ + UPDATE_RULE, + + /** Rule for updating a foreign key when the primary key is deleted. */ + DELETE_RULE, + + /** Foreign key name. */ + FK_NAME, + + /** Primary key name. */ + PK_NAME, + + /** Deferrability of foreign key */ + DEFERRABILITY + }; +}; +} // namespace + namespace ignite { namespace odbc { namespace query { -ForeignKeysQuery::ForeignKeysQuery( - diagnostic::DiagnosableAdapter& diag, Connection& connection, - const std::string& primaryCatalog, const std::string& primarySchema, - const std::string& primaryTable, const std::string& foreignCatalog, - const std::string& foreignSchema, const std::string& foreignTable) +ForeignKeysQuery::ForeignKeysQuery(diagnostic::DiagnosableAdapter& diag, + Connection& connection, + const boost::optional< std::string >& catalog, + const boost::optional< std::string >& schema, + const std::string& table) : Query(diag, QueryType::FOREIGN_KEYS), connection(connection), - primaryCatalog(primaryCatalog), - primarySchema(primarySchema), - primaryTable(primaryTable), - foreignCatalog(foreignCatalog), - foreignSchema(foreignSchema), - foreignTable(foreignTable), + catalog(catalog), + schema(schema), + table(table), executed(false), columnsMeta() { using namespace ignite::odbc::impl::binary; @@ -51,38 +103,34 @@ ForeignKeysQuery::ForeignKeysQuery( const std::string sch(""); const std::string tbl(""); - columnsMeta.push_back( - ColumnMeta(sch, tbl, "PKTABLE_CAT", IGNITE_TYPE_STRING, Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_SCHEM", - IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_NAME", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "PKCOLUMN_NAME", - IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_CAT", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_SCHEM", - IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_NAME", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "FKCOLUMN_NAME", - IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ", IGNITE_TYPE_SHORT, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "UPDATE_RULE", IGNITE_TYPE_SHORT, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "DELETE_RULE", IGNITE_TYPE_SHORT, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "FK_NAME", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME", IGNITE_TYPE_STRING, - Nullability::NULLABILITY_UNKNOWN)); - columnsMeta.push_back(ColumnMeta(sch, tbl, "DEFERRABILITY", IGNITE_TYPE_SHORT, - Nullability::NULLABILITY_UNKNOWN)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_CAT", JDBC_TYPE_VARCHAR, + Nullability::NULLABLE)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_SCHEM", JDBC_TYPE_VARCHAR, + Nullability::NULLABLE)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "PKTABLE_NAME", JDBC_TYPE_VARCHAR, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "PKCOLUMN_NAME", JDBC_TYPE_VARCHAR, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_CAT", JDBC_TYPE_VARCHAR, + Nullability::NULLABLE)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_SCHEM", JDBC_TYPE_VARCHAR, + Nullability::NULLABLE)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "FKTABLE_NAME", JDBC_TYPE_VARCHAR, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "FKCOLUMN_NAME", JDBC_TYPE_VARCHAR, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "KEY_SEQ", JDBC_TYPE_SMALLINT, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "UPDATE_RULE", JDBC_TYPE_SMALLINT, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "DELETE_RULE", JDBC_TYPE_SMALLINT, + Nullability::NO_NULL)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "FK_NAME", JDBC_TYPE_VARCHAR, + Nullability::NULLABLE)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "PK_NAME", JDBC_TYPE_VARCHAR, + Nullability::NULLABLE)); + columnsMeta.push_back(ColumnMeta(sch, tbl, "DEFERRABILITY", + JDBC_TYPE_SMALLINT, Nullability::NO_NULL)); } ForeignKeysQuery::~ForeignKeysQuery() { @@ -90,16 +138,27 @@ ForeignKeysQuery::~ForeignKeysQuery() { } SqlResult::Type ForeignKeysQuery::Execute() { - executed = true; + if (executed) + Close(); - return SqlResult::AI_SUCCESS; + SqlResult::Type result = MakeRequestGetForeignKeysMeta(); + + if (result == SqlResult::AI_SUCCESS) { + executed = true; + fetched = false; + + cursor = meta.begin(); + } + + return result; } const meta::ColumnMetaVector* ForeignKeysQuery::GetMeta() { return &columnsMeta; } -SqlResult::Type ForeignKeysQuery::FetchNextRow(app::ColumnBindingMap&) { +SqlResult::Type ForeignKeysQuery::FetchNextRow( + app::ColumnBindingMap& columnBindings) { if (!executed) { diag.AddStatusRecord(SqlState::SHY010_SEQUENCE_ERROR, "Query was not executed."); @@ -107,11 +166,24 @@ SqlResult::Type ForeignKeysQuery::FetchNextRow(app::ColumnBindingMap&) { return SqlResult::AI_ERROR; } - return SqlResult::AI_NO_DATA; + if (!fetched) + fetched = true; + else + ++cursor; + + if (cursor == meta.end()) + return SqlResult::AI_NO_DATA; + + app::ColumnBindingMap::iterator it; + + for (it = columnBindings.begin(); it != columnBindings.end(); ++it) + GetColumn(it->first, it->second); + + return SqlResult::AI_SUCCESS; } -SqlResult::Type ForeignKeysQuery::GetColumn(uint16_t, - app::ApplicationDataBuffer&) { +SqlResult::Type ForeignKeysQuery::GetColumn( + uint16_t columnIdx, app::ApplicationDataBuffer& buffer) { if (!executed) { diag.AddStatusRecord(SqlState::SHY010_SEQUENCE_ERROR, "Query was not executed."); @@ -119,17 +191,100 @@ SqlResult::Type ForeignKeysQuery::GetColumn(uint16_t, return SqlResult::AI_ERROR; } - return SqlResult::AI_NO_DATA; + if (cursor == meta.end()) + return SqlResult::AI_NO_DATA; + + const meta::ForeignKeyMeta& currentColumn = *cursor; + + switch (columnIdx) { + case ResultColumn::PKTABLE_CAT: { + buffer.PutString(currentColumn.GetPKCatalogName()); + break; + } + + case ResultColumn::PKTABLE_SCHEM: { + buffer.PutString(currentColumn.GetPKSchemaName()); + break; + } + + case ResultColumn::PKTABLE_NAME: { + buffer.PutString(currentColumn.GetPKTableName()); + break; + } + + case ResultColumn::PKCOLUMN_NAME: { + buffer.PutString(currentColumn.GetPKColumnName()); + break; + } + + case ResultColumn::FKTABLE_CAT: { + buffer.PutString(currentColumn.GetFKCatalogName()); + break; + } + + case ResultColumn::FKTABLE_SCHEM: { + buffer.PutString(currentColumn.GetFKSchemaName()); + break; + } + + case ResultColumn::FKTABLE_NAME: { + buffer.PutString(currentColumn.GetFKTableName()); + break; + } + + case ResultColumn::FKCOLUMN_NAME: { + buffer.PutString(currentColumn.GetFKColumnName()); + break; + } + + case ResultColumn::KEY_SEQ: { + buffer.PutInt16(currentColumn.GetKeySeq()); + break; + } + + case ResultColumn::UPDATE_RULE: { + buffer.PutInt16(currentColumn.GetUpdateRule()); + break; + } + + case ResultColumn::DELETE_RULE: { + buffer.PutInt16(currentColumn.GetDeleteRule()); + break; + } + + case ResultColumn::FK_NAME: { + buffer.PutString(currentColumn.GetFKName()); + break; + } + + case ResultColumn::PK_NAME: { + buffer.PutString(currentColumn.GetPKName()); + break; + } + + case ResultColumn::DEFERRABILITY: { + buffer.PutInt16(currentColumn.GetDeferrability()); + break; + } + + default: + break; + } + + return SqlResult::AI_SUCCESS; } SqlResult::Type ForeignKeysQuery::Close() { + meta.clear(); + executed = false; + fetched = false; return SqlResult::AI_SUCCESS; } bool ForeignKeysQuery::DataAvailable() const { - return false; + return cursor != meta.end(); } int64_t ForeignKeysQuery::AffectedRows() const { return 0; @@ -138,6 +293,41 @@ int64_t ForeignKeysQuery::AffectedRows() const { SqlResult::Type ForeignKeysQuery::NextResultSet() { return SqlResult::AI_NO_DATA; } + +SqlResult::Type ForeignKeysQuery::MakeRequestGetForeignKeysMeta() { + IgniteError error; + SharedPointer< DatabaseMetaData > databaseMetaData = + connection.GetMetaData(error); + if (!databaseMetaData.IsValid() + || error.GetCode() != IgniteError::IGNITE_SUCCESS) { + diag.AddStatusRecord(error.GetText()); + return SqlResult::AI_ERROR; + } + + JniErrorInfo errInfo; + SharedPointer< ResultSet > resultSet = + databaseMetaData.Get()->GetImportedKeys(catalog, schema, table, errInfo); + if (!resultSet.IsValid() + || errInfo.code != JniErrorCode::IGNITE_JNI_ERR_SUCCESS) { + diag.AddStatusRecord(errInfo.errMsg); + return SqlResult::AI_ERROR; + } + + meta::ReadForeignKeysColumnMetaVector(resultSet, meta); + + for (size_t i = 0; i < meta.size(); ++i) { + LOG_DEBUG_MSG("\n[" << i << "] PKSchemaName: " + << meta[i].GetPKSchemaName().get_value_or("") << "\n[" + << i << "] PKTableName: " + << meta[i].GetPKTableName().get_value_or("") << "\n[" + << i << "] PKColumnName: " + << meta[i].GetPKColumnName().get_value_or("") << "\n[" + << i << "] KeySeq: " + << meta[i].GetKeySeq()); + } + + return SqlResult::AI_SUCCESS; +} } // namespace query } // namespace odbc } // namespace ignite diff --git a/src/odbc/src/statement.cpp b/src/odbc/src/statement.cpp index 5519ddaf3..a3fa0da2d 100644 --- a/src/odbc/src/statement.cpp +++ b/src/odbc/src/statement.cpp @@ -697,24 +697,24 @@ SqlResult::Type Statement::InternalExecuteGetTablesMetaQuery( void Statement::ExecuteGetForeignKeysQuery(const std::string& primaryCatalog, const std::string& primarySchema, const std::string& primaryTable, - const std::string& foreignCatalog, - const std::string& foreignSchema, + const boost::optional< std::string >& foreignCatalog, + const boost::optional< std::string >& foreignSchema, const std::string& foreignTable) { IGNITE_ODBC_API_CALL(InternalExecuteGetForeignKeysQuery( primaryCatalog, primarySchema, primaryTable, foreignCatalog, foreignSchema, foreignTable)); } -SqlResult::Type Statement::InternalExecuteGetForeignKeysQuery( - const std::string& primaryCatalog, const std::string& primarySchema, - const std::string& primaryTable, const std::string& foreignCatalog, - const std::string& foreignSchema, const std::string& foreignTable) { +SqlResult::Type Statement::InternalExecuteGetForeignKeysQuery(const std::string& primaryCatalog, const std::string& primarySchema, + const std::string& primaryTable, + const boost::optional< std::string >& foreignCatalog, + const boost::optional< std::string >& foreignSchema, + const std::string& foreignTable) { if (currentQuery.get()) currentQuery->Close(); currentQuery.reset(new query::ForeignKeysQuery( - *this, connection, primaryCatalog, primarySchema, primaryTable, - foreignCatalog, foreignSchema, foreignTable)); + *this, connection, foreignCatalog, foreignSchema, foreignTable)); return currentQuery->Execute(); } diff --git a/src/odbc/src/utility.cpp b/src/odbc/src/utility.cpp index 4926712be..bb5404309 100644 --- a/src/odbc/src/utility.cpp +++ b/src/odbc/src/utility.cpp @@ -140,6 +140,27 @@ std::string SqlStringToString(const unsigned char* sqlStr, int32_t sqlStrLen) { return res; } +boost::optional< std::string > SqlStringToOptString(const unsigned char* sqlStr, + int32_t sqlStrLen) { + boost::optional< std::string > res = boost::none; + std::string tmp; + + const char* sqlStrC = reinterpret_cast< const char* >(sqlStr); + + if (!sqlStr) + return res; + + if (sqlStrLen == SQL_NTS) { + tmp.assign(sqlStrC); + res = tmp; + } else if (sqlStrLen > 0) { + tmp.assign(sqlStrC, sqlStrLen); + res = tmp; + } + + return res; +} + void ReadByteArray(BinaryReaderImpl& reader, std::vector< int8_t >& res) { int32_t len = reader.ReadInt8Array(0, 0); From 9cc2a02c0cf6f1398115552c31aa98ae267757c3 Mon Sep 17 00:00:00 2001 From: Bruce Irschick Date: Thu, 26 May 2022 15:08:55 -0700 Subject: [PATCH 149/165] [AD-649] Add missing documentation (#29) ### Summary [AD-649] Add missing documentation ### Description Update ODBC driver documentation - [x] Documentation about connections string ( Parameters description) - [x] Documentation about DSN configuration window ( with screenshots) - [x] Documentation how the ODBC driver works ( ODBC and JDBC integration) - [x] Documentation what is supported ( link with JDBC driver) ### Related Issue https://bitquill.atlassian.net/browse/AD-649 * Updating JDBC version (#72) * [AD-370] upload odbc driver build on push to develop (#71) * [AD-730] upload odbc driver build at push to develop * [AD-730] update github actions to upload with v3 * [AD-730] Test artifact upload action * temporarily comment out if statement guard to test upload-artifact github action * [AD-730] upload performance test executable * [AD-730] update readme * [AD-730] upload Release folder as artifact * our odbc needs more than just the ignite.odbc.dll to run properly * [AD-730] update to upload artifacts for release build * previously, I uploaded the Debug builds, but the Release build is the one that requires less dependencies. * [AD-730] add back if statment * add the if statement back in win-build.yml to ensure that the odbc driver performance artifact is only published when pushed to develop * [AD-730] fix typo of performance test plan * [AD-735] large dataset crash issue (#74) ### Summary ODBC driver will not run on large document tests ### Description The performance test crashes for large document tests. 1. The root cause is the wrong memory is passed to SQLBindCol(). The parameter TargetValuePtr is passed &cols[i][0].data_dat[i]. The i could exceed 255 for large table while its max valid value should be 254. The correct value should be 0. 2. The SQLExtendedFetch is deprecated. Replace it with SQLFetch. ### Related Issue https://bitquill.atlassian.net/browse/AD-735 * [AD-509] Update mac developer environment setup * Adjust formatting * Add note about llvm * Add note about iodbc * Update README.md change the install options for OpenSSL, since vcpkg is a preferred option * Update README.md remove the WiX Toolset v4 requirement * Update README.md add steps for the fix for ignite-odbc-tests.profraw error in README. * [AD-517] Remove old properties + add new properties * remove SSL settings and add TLS checkbox on the Configuration Window * add comments for my own work added some comments for my own convenience. Will remove later * fix tls checkbox on Configuration Window fixed by updating ChildId in tlsCheckBox = CreateCheckBox * add TlsAllowInvalidHostnames checkbox and TLS CA edit to the Configuration Window * Update configuration.cpp add comment to illustrate plan on what to do for the configuration window * Update dsn_configuration_window.cpp bugfix to make tlsCheckBox and tlsAllowInvalidHostnamesCheckBox read into the saved values * change defaultFetchSize to fetchSize in configuration.h * change Default DSN name to DocumentDB DSN * add App Name, Fetch Size, Read Preference, and login timeout to configuration window * [AD-522] bugfix - change DefaultFetchSize to fetchSize in all related files to be consistent with configuration.h Files that had the change connection_string_parser.cpp, connection_string_parser.h, dsn_config.cpp, batch_query.cpp, data_query.cpp. * [AD-522] save read preference settings * [AD-522] remove commented out code * [AD-522] Implement replicaSet and retryReads on Configuration Window * [AD-517] Re-enable unit tests - WIP - still need to cleanup * [AD-522] add space to code lines for format consistency in configuration_window.h * Add more unit tests * Remove extra file * [AD-522] Add small letter case to keep format consistency in dsn_configuration_window.h Add small letter case to keep format consistency in dsn_configuration_window.h fixed one typo (Create authentication settings group box) * Remove redundant declaration * [AD-522] add variable definitions for SSH tunnel settings for config UI * [AD-522] add function definition for SSH Tunnel added SSH User, SSH Host. SSH Strict Host Key Checking, and SSH Known Hosts File onto the UI. However, the code to save the written values would be done in later commits. * [AD-522] code draft for configuration.cpp add draft variable definition to Enable ssh tunnel boolean value * Revert "change defaultFetchSize to fetchSize in configuration.h" This reverts commit f311e3bc7df1fd66d7be66c8e60170a41d078c18. * Revert "[AD-522] bugfix - change DefaultFetchSize to fetchSize in all related files to be consistent with configuration.h" This reverts commit 2bcd2a492bd69fbde5de986a03c5a407a729ba47. * [AD-517] * Change the C++ version to use to compile. * [AD-522] change fetchSize to defaultFetchSize on configuration window for consistency with JDBC driver * [AD-517] * Changed checks.yml so that it doesn't fail on code review errors. * Revert "[AD-522] bugfix - change DefaultFetchSize to fetchSize in all related files to be consistent with configuration.h"" This reverts commit 124b7256d8f96fb31363aa2efb0423b115b11b0a. * [AD-522] make TLS allow invalid hostnames checkbox enabled only when tls Check box is checked * Revert "Revert "[AD-522] bugfix - change DefaultFetchSize to fetchSize in all related files to be consistent with configuration.h""" This reverts commit aa7731a67f123c8942b89cba8334efe15776f6c8. * Improvements from review * Updated comments * [AD-522] save SSH values for re-read, make settings window into 2 columns Make ssl and additional settings groups to be on the right side of the column on the configuration window. This is subject to change later. I created the function void DsnConfigurationWindow::RetrieveSshParameters(config::Configuration& cfg) const to save SSH values. The width value in the DsnConfigurationWindow constructor is doubled from 360 to 720 and added the margin value. The margins currently look imbalanced on the settings box, and will be fixed in later commits. Make Ok button and Cancel buttons aligned with the right column bugfix - allow the SSH strict host checking checkbox to be checked on and off by adding the case ChildId::SSH_STRICT_HOST_KEY_CHECKING_CHECK_BOX definition. * Removed includes no longer being used in configuration.h * Some formatting improvements * [Ad-522] add sshEnable variable in DSN config - added sshEnable variable definition and getter/setter for sshEnable. - added code for parsing sshEnable in the connection string parser * [AD-522] change from GetSshEnable to IsSshEnable for consistency * [AD-522] comment out deprecated readPreference variable start on transitioning from readPreferenceEdit to readPreference combo box * [AD-522] add SSH enable checkbox, SSH private key passphrase, and SSH private key file * add SSH Enable variable in configuration.h and configuration.cpp * add SSH checkbox in SSH group setting * add SSH private key file edit in SSH group setting * add SSH private key pass phrase in SSH group setting ** SSH private key passphrase label requires double the row height due to the label being long. * make SSH setting items disabled/enabled as SSH enable checkbox is unchecked/checked * save SSH variables to configuration when Ok button is pressed. * [AD-522] read_preference.h fix * add guards to read_preference.h fix * include read_preference.h in dsn_configuration_window.cpp * add draft code for read preference in dsn_configuration_window.cpp * [AD-522] update fields in configuration window * modified order of fields in the configuration window. - Retry reads checkbox is now in the first row under "Additional Settings". - SSH Strict host key check is now in the last row under "Internal SSH Tunnel Settings" - Allow invalid hostnames checkbox now is in 2nd row under "TLS/SSL settings" * added warning sentences for Allow invalid hostnames checkbox and SSH strict host key check * Improvements from code review + address some warnings * Change connection _test to use hostname key instead of address * Change connection_test to use databse key instead of schema key * [AD-522] implement read Preference * add SpaceToUnderscore function * implement read Preference in Config window and save the value * Attempt to fix windows 32 build * [AD-522] refactor dsn_configuration_window.cpp refactor code format; remove spaces and unnecessary comments * [AD-522] fix config window margins now the config window is symmetric * Fix formatting * [AD-522] add HasText() function to window.h * previously, the definition of HasText was mistakenly committed in commit cbaeedd0cde8b82bc29134efcad28dba943751c2. * add header of HasText() to resolve building errors in origin * update HasText() function to make code simpler * [AD-522] make "rs0" the default value of replicaSet * [AD-522] implement database, hostname, port fields. And disable ok button unless all required fields are filled * implement database, hostname, port fields. * disable ok button unless all required fields (database, hostname, port, username, password) are filled * added boolean created to indicate whether the configuration window has been created. If has, then check for disabling/enabling the Ok button * [AD-522] rename SSH Known Hosts File label for clarity * [AD-522] refactor logs for retrieving TSL settings Make the sentences align * [AD-522] rename TLS CA File label for clarity * change label length to the same label length as connection settings group * [AD-522] move authorization setting fields to connection fields reason: only username and password are authorization settings, the rest are not. We chose to put username, password in the connections group because all fields in the connections group are required. * [AD-522] bugfix-comment out address field related code in RetrieveConnectionParameters * [AD-522] rename sslSettings to tlsSettings and add comment for connection settings group * [AD-522] remove protocol version from config window * [AD-522] bug fix sshKnownHostsFile not saved when Ok button is pressed * [AD-522] remove commented out #include headers * [AD-522] disable SSH Known Hosts File edit when SSH Strict Host Key Check check box is unchecked * move SSH Strict Host Key Checking check box above SSH Known Hosts File edit in the config window * [AD-522] refactor - remove commented out header code * [AD-522] add comments in configuration.cpp for planning * modify commented out example code in dsn_configuration_window.cpp for clarity * [AD-522] change from SSL to TLS for consistency * SSL_SETTINGS_GROUP_BOX is changed to TLS_SETTINGS_GROUP_BOX * [AD-522] remove commented out code Removed commented out code: * RetrieveAuthParameters * CreateAuthSettingsGroup * CreateAdditionalSettingsGroup function and CreateSslSettingsGroup function for 1 column window * protocol version - related code * authSettingsGroupBox code * [AD-522] remove std::auto_ptr authSettingsGroupBox; * [AD-522] remove address field auto pointer initialization * [AD-522] remove address field from config window constructor * [AD-522] refactor - remove unneeded commented out code in HasText * [AD-522] refactor - remove white spaces and update comment * [AD-522] debug scan_method.h * SpaceToUnderscore is called in scan_method.cpp to make reads better * added guards to scan_method.h * [AD-522] implement Schema group settings box * fixed bug in dsn_config.cpp to save scanLimit correctly * [AD-522] update readPreference default value to unknown * removed unneeded commented out code * removed unnecessary code to get string value on readPreference * [AD-522] refactor - remove unnecessary comments * [AD-522] adjust window size and additional settings group label size * additional settings group label size is now the same as other settings group in the same column * Revert "Merge branch 'develop' into alinaliBQ/AD-522/config_window" This reverts commit 8d609dac52d3e3fc0442f2e8ec8526ec3eb2d6ab, reversing changes made to 0aa20527606ccc11a7a99d6bd6f8d249fa8d1f61. * [AD-522] keyboard user interface design + disable DSN empty strimg warning dialog * make cursor go to checkboxes on the Config window and not skip them when tab key is pressed * when DSN field is empty, Ok Button is disabled * make default replicaSet value empty string (default is disable repliaSet) * refactor - removed unneeded comments * [AD-522] add end_point header to resolve build errors end_point related code still exist in connection.cpp, so I readded the header for end_point * Revert "Revert "Merge branch 'develop' into alinaliBQ/AD-522/config_window"" This reverts commit df0cad5490612c695ca28cc8ee44c73dbb1b68bd. * [AD-522] resolve errors after merging develop branch * GetAddresses() is deprecated, replaced it with GetHostname() and GetTcpPort() to get hostname and port number, respectively. * replaced GetSchema() with GetSchemaName() * removed commented out code * refactor with dsn_configuration_window.cpp * [AD-512] Resolve issue with missing include file. * [AD-522] make BoolParseResult recognizable * [AD-522] fix build errors after develop branch merge * update schema checkbox string * make edit row height single * update SetTcpPort to SetPort etc * define default value for sshEnable * [AD-522] enable encrypt password for ssh private key passphrase * modify refresh schema checkbox string to fit better * remove log message for ssh private key passphrase to increase security * [AD-521] add comments and notes for starting AD-521 * [AD-509] update readMe to include directions about saving Java bin and server directories. * reason: ODBC JNI calls have a dependency on `jvm.dll`, as a result, the ODBC driver cannot operate properly unless the Java bin and server directories are included in the path. * [AD-522] reduce space between ssh private key passphrase and the checkbox below * [AD-521] define constants for Java GetSshLocalPort method call * [AD-521] integrate code review feedback from Andie * refactors with comment changes and log changes * [AD-521] refactor code * make open brace bracket start on new line for JVMException * remove excess space * [AD-427] Tracer Code - Limited Capability to load metadata - work-in-progress. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Windows build. * [AD-427] Fix Windows build. * [AD-427] Fix Windows build. * [AD-522] remove space and add new line at the end of enum types * [AD-522] add new lines at the end of Enum type files * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-521] add changes for Java.cpp from Bruce's AD-427 branch * those changes are not included in the previous merge, and are now added * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-427] Fix Mac build. * [AD-521] JNI wrapper calls to iSshTunnelActive and getSshLocalPort * some draft comments are left to be cleaned up * [AD-521] debug getSshLocalPort * change function type signature from optional to int * refactor - remove comments * [AD-521] change return value in getSshLocalPort from boolean to a 0 * try to fix access memory issue in TestDriverManagerGetConnection * [AD-522] resolve build errors after merge * fix bug for schema name not correctly loaded on the config window * removed unnecessary headers * [AD-427] Added ResultSet.next and ResultSet.GetString() * [AD-522] address code review comments * change to enum class type for read_preference.h and scan_method.h * change the way enum class objects are read * add static cast to enum types so SetSelection function can work with it * refactor - removed unnecessary comments * refactor - changes code doc in connection_string_parser.h * [AD-521] implement tests for JNI wrapper code * test for TestDocumentDbConnectionGetSshTunnelPortSshTunnelNotActive is not yet active, need to be enabled when we can get external SSH tunnel working. * bug fix: re-implemented DocumentDbConnectionGetSshLocalPort and DocumentDbConnectionIsSshTunnelActive. connection.Get()->GetRef() is passed as first parameter because jobject is required for CallIntMethod and CallBooleanMethod. * better JNI wrapper code is needed in the future so warnings/errors pop up when we pass jobject instead of jclass to the methods. * [AD-521] refactor - remove comments and commented out code * [AD-589] implement JNI method call for GetDatabaseMetadata * define the method constant for DocumentDbConnection.getDatabaseMetadata() * create JNI wrapper function for DocumentDbConnection.getMetaData * [AD-589] implement unit test for DocumentDbConnection.getMetaData * [AD-521] add calls to AutoCloseConnection in unit tests * pass & errInfo instead of * errInfo in DocumentDbConnectionGetSshLocalPort and DocumentDbConnectionIsSshTunnelActive. * [AD-521] remove unnecessary comment * [AD-589] fix merge issues * I missed this part of code when I was resolving the merge conflicts. Now they are corrected * [AD-589] update getMetaData JNI wrapper code to pass &errInfo * implement unit test for getMetaData * [AD-589] implement JNI wrapper for DocumentDbDatabaseSchemaMetadataGetSchemaName * implement Java class for * define constant for DocumentDbDatabaseSchemaMetadataGetSchemaName * add empty test function for TestDocumentDbDatabaseSchemaMetadataGetSchemaName * [AD-589] implement unit test for DbDatabaseSchemaMetadataGetSchemaName * [AD-521] refactor - change case of ssh to SSH for consistency * [AD-589] address code review comments * rename DocumentDbConnectionGetMetaData to DocumentDbConnectionGetDatabaseMetaData * [AD-589] change case from MetaData to Metadata to match Java method name * [AD-589] refactor: change from metaData to metadata changes occurred in: * DocumentDbConnectionGetDatabaseMetadata * DocumentDbDatabaseSchemaMetadataGetSchemaName * TestDocumentDbConnectionGetDatabaseMetadata * TestDocumentDbDatabaseSchemaMetadataGetSchemaName * Birschick bq/sync up (#21) * Updating JDBC version (#72) * [AD-370] upload odbc driver build on push to develop (#71) * [AD-730] upload odbc driver build at push to develop * [AD-730] update github actions to upload with v3 * [AD-730] Test artifact upload action * temporarily comment out if statement guard to test upload-artifact github action * [AD-730] upload performance test executable * [AD-730] update readme * [AD-730] upload Release folder as artifact * our odbc needs more than just the ignite.odbc.dll to run properly * [AD-730] update to upload artifacts for release build * previously, I uploaded the Debug builds, but the Release build is the one that requires less dependencies. * [AD-730] add back if statment * add the if statement back in win-build.yml to ensure that the odbc driver performance artifact is only published when pushed to develop * [AD-730] fix typo of performance test plan Co-authored-by: affonsoBQ <67347924+affonsoBQ@users.noreply.github.com> Co-authored-by: Alina (Xi) Li <96995091+alinaliBQ@users.noreply.github.com> * [AD-735] large dataset crash issue (#23) * first test * fix performance test crash * fix performance test crash * fix whitespace issue * rework based on comments Co-authored-by: Andie Montoya Co-authored-by: Alina (Xi) Li <96995091+alinaliBQ@users.noreply.github.com> Co-authored-by: Alina (Xi) Li Co-authored-by: affonsoBQ <67347924+affonsoBQ@users.noreply.github.com> Co-authored-by: RoyZhang2022 <104782736+RoyZhang2022@users.noreply.github.com> * [AD-649] Add missing documentation (#73) * Initial user/developer documentation Co-authored-by: andiem-bq <67925459+andiem-bq@users.noreply.github.com> Co-authored-by: Bruce Irschick Co-authored-by: Alina (Xi) Li <96995091+alinaliBQ@users.noreply.github.com> Co-authored-by: affonsoBQ <67347924+affonsoBQ@users.noreply.github.com> Co-authored-by: Alina (Xi) Li <96995091+alinaliBQ@users.noreply.github.com> Co-authored-by: Andie Montoya Co-authored-by: Alina (Xi) Li Co-authored-by: RoyZhang2022 <104782736+RoyZhang2022@users.noreply.github.com> --- README.md | 48 +--- .../{ => images}/dotNet_screenshot.PNG | Bin .../images/odbc-data-source-admin.png | Bin 0 -> 146112 bytes .../images/windows-dsn-configuration.png | Bin 0 -> 286970 bytes src/markdown/index.md | 98 +++++++ src/markdown/setup/connection-string.md | 100 +++++++ src/markdown/setup/developer-guide.md | 244 ++++++++++++++++++ src/markdown/setup/dsn-configuration.md | 5 + src/markdown/setup/linux-dsn-configuration.md | 0 src/markdown/setup/macOS-dsn-configuration.md | 0 src/markdown/setup/microsoft-power-bi.md | 0 src/markdown/setup/setup.md | 121 +++++++++ .../setup/windows-dsn-configuration.md | 8 + .../{ => support}/troubleshooting-guide.md | 0 14 files changed, 589 insertions(+), 35 deletions(-) rename src/markdown/{ => images}/dotNet_screenshot.PNG (100%) create mode 100644 src/markdown/images/odbc-data-source-admin.png create mode 100644 src/markdown/images/windows-dsn-configuration.png create mode 100644 src/markdown/index.md create mode 100644 src/markdown/setup/connection-string.md create mode 100644 src/markdown/setup/developer-guide.md create mode 100644 src/markdown/setup/dsn-configuration.md create mode 100644 src/markdown/setup/linux-dsn-configuration.md create mode 100644 src/markdown/setup/macOS-dsn-configuration.md create mode 100644 src/markdown/setup/microsoft-power-bi.md create mode 100644 src/markdown/setup/setup.md create mode 100644 src/markdown/setup/windows-dsn-configuration.md rename src/markdown/{ => support}/troubleshooting-guide.md (100%) diff --git a/README.md b/README.md index 175f95be8..8816ba93c 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,30 @@ # Amazon DocumentDB ODBC Driver -## Development Environment +## Overview -### Pre-requisites +The ODBC driver for the Amazon DocumentDB managed document database provides an +SQL-relational interface for developers and BI tool users. -#### C/C++ Formatting +## Security -- This project uses [Google's C++ Style Guide](https://google.github.io/styleguide/cppguide.htm) as a basis for -C/C++ usage and formatting. -- Some formatting is set using the .clang-format file at the base of repository. Other options for Visual Studio can be imported from the -`VS-C++-Settings-Export.vssettings` file also found at root of repository. +See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information. -#### Environment Variables for Testing Accounts/Secrets -To enable the test environment to run the tests against a live DocumentDB system, set the following environment variables on your development machine. +## License -DocumentDB cluster credentials -1. `DOC_DB_HOST`=``(e.g.:`docdb-host.us-east-2.docdb.amazonaws.com`) -2. `DOC_DB_PASSWORD`=`` -3. `DOC_DB_USER_NAME`=`` +This project is licensed under the Apache-2.0 License. -SSH host credentials -1. `DOC_DB_USER`=``(e.g.:`ec2-user@ec2-instance.us-east-2.compute.amazonaws.com`) -2. `DOC_DB_PRIV_KEY_FILE`=``(e.g.:`~/.ssh/ssh_host.pem`) +## Documentation -[`Optional`] Log configurations +See the [product documentation](src/markdown/index.md) for more detailed information about this driver, such as setup and configuration. -Set these 2 variables only if you would like to set a custom log path or log level for connection tests; it is completely optional. -1. `DOC_DB_LOG_PATH`=``(e.g.:`"C:\\Users\\BitQuillUser\\Desktop\\DocumentDB ODBC Driver"`) +## Setup and Usage - The user needs to ensure that the directory mentioned in the log file path does exist, or driver will ignore user's passed value and create the log file in the default log path. Do **not** include a slash at the end of the log path. +To setup and use the DocumentDB ODBC driver, follow [these directions](src/markdown/setup/setup.md). - The log path indicates the path to store the log file. The log file name has `docdb_odbc_YYYYMMDD.log` format, - where `YYYYMMDD` (e.g., 20220225 <= Feb 25th, 2022) is the date at the first log message. +## Connection String Syntax -2. `DOC_DB_LOG_LEVEL`=``. The default is `error` level. (Choose from `debug`, `info`, `error`, `off`) - - More details about logging in [`src\markdown\troubleshooting-guide.md`](src/markdown/troubleshooting-guide.md). - -#### Running an SSH tunnel for Testing -By default, remote integration tests are not run. To enable remote integration tests, -set the environment variable `DOC_DB_ODBC_INTEGRATION_TEST=1` -To run tests that require an external SSH tunnel, you will need to start an SSH tunnel using the same values as the environment variables set in the previous section. -If the local port is a value other than 27019, set `DOC_DB_LOCAL_PORT` to that value. -If the remote port is a value other than 27017, set `DOC_DB_REMOTE_PORT` to that value. - -Example: ``` - ssh -i $DOC_DB_PRIV_KEY_FILE -N -L $DOC_DB_LOCAL_PORT:$DOC_DB_HOST:$DOC_DB_REMOTE_PORT $DOC_DB_USER +DRIVER={Amazon DocumentDB};HOSTNAME=:;DATABASE=;USER=;PASSWORD=;