From 1d252550161360993827d011e1a1e9b1945308af Mon Sep 17 00:00:00 2001 From: Cristian Ferretti <37232625+jcferretti@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:47:21 -0700 Subject: [PATCH] fix(cpp-client) Update C++ and R client (#5807) Co-authored-by: Corey Kosak Co-authored-by: Alex Peters <80283343+alexpeters1208@users.noreply.github.com> --- R/build.gradle | 5 +- RELEASE.md | 1 + cpp-client/README.md | 101 +- cpp-client/build.gradle | 2 + cpp-client/deephaven/CMakeLists.txt | 38 +- .../deephaven/cmake/deephavenConfig.cmake | 9 + cpp-client/deephaven/dhclient/CMakeLists.txt | 16 +- .../deephaven/client/interop/client_interop.h | 678 ++++++++ .../client/interop/client_options_interop.h | 57 + .../client/interop/update_by_interop.h | 195 +++ .../public/deephaven/client/update_by.h | 6 +- .../deephaven/client/utility/table_maker.h | 193 ++- .../dhclient/src/interop/client_interop.cc | 1370 +++++++++++++++++ .../src/interop/client_options_interop.cc | 118 ++ .../dhclient/src/interop/update_by_interop.cc | 435 ++++++ cpp-client/deephaven/dhcore/CMakeLists.txt | 8 +- .../deephaven/dhcore/clienttable/schema.h | 6 +- .../deephaven/dhcore/interop/interop_util.h | 254 +++ .../testapi/basic_interop_interactions.h | 143 ++ .../dhcore/src/clienttable/schema.cc | 4 +- .../dhcore/src/interop/interop_util.cc | 69 + .../testapi/basic_interop_interactions.cc | 99 ++ .../deephaven/tests/src/add_drop_test.cc | 2 +- .../deephaven/tests/src/attributes_test.cc | 2 +- cpp-client/deephaven/tests/src/join_test.cc | 11 - cpp-client/deephaven/tests/src/sort_test.cc | 6 - .../deephaven/tests/src/ungroup_test.cc | 8 +- .../deephaven/tests/src/update_by_test.cc | 1 - .../deephaven/tests/src/validation_test.cc | 55 +- cpp-client/deephaven/vcpkg-configuration.json | 2 +- cpp-client/deephaven/vcpkg.json | 2 +- 31 files changed, 3735 insertions(+), 161 deletions(-) create mode 100644 cpp-client/deephaven/cmake/deephavenConfig.cmake create mode 100644 cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/client_interop.h create mode 100644 cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/client_options_interop.h create mode 100644 cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/update_by_interop.h create mode 100644 cpp-client/deephaven/dhclient/src/interop/client_interop.cc create mode 100644 cpp-client/deephaven/dhclient/src/interop/client_options_interop.cc create mode 100644 cpp-client/deephaven/dhclient/src/interop/update_by_interop.cc create mode 100644 cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/interop/interop_util.h create mode 100644 cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/interop/testapi/basic_interop_interactions.h create mode 100644 cpp-client/deephaven/dhcore/src/interop/interop_util.cc create mode 100644 cpp-client/deephaven/dhcore/src/interop/testapi/basic_interop_interactions.cc diff --git a/R/build.gradle b/R/build.gradle index 85583260473..68d1b704599 100644 --- a/R/build.gradle +++ b/R/build.gradle @@ -179,7 +179,10 @@ def rClientSite = Docker.registerDockerTask(project, 'rClientSite') { runCommand("mkdir -p ${prefix}/src/rdeephaven/docs") runCommand('''echo "status = tryCatch(" \ " {" \ - " install.packages('pkgdown', repos='https://cran.r-project.org'); " \ + " install.packages('devtools'); " \ + " require(devtools); " \ + " remove.packages('pkgdown'); " \ + " devtools::install_version('pkgdown', version='2.0.0', repos='https://cran.r-project.org'); " \ " 0" \ " }," \ " error=function(e) 1," \ diff --git a/RELEASE.md b/RELEASE.md index 7fe5e8f7c8e..ea96f9d9984 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -283,6 +283,7 @@ mention the version explicitly. These files are listed below: # gradle.properties R/rdeephaven/DESCRIPTION +cpp-client/deephaven/CMakeLists.txt ``` This leaves the files "ready" for the next regular release, and also ensures any build done from diff --git a/cpp-client/README.md b/cpp-client/README.md index d11aae49899..1c5e35212c7 100644 --- a/cpp-client/README.md +++ b/cpp-client/README.md @@ -11,13 +11,26 @@ on them anymore so we do not guarantee they are current for those platforms. Instructions for Linux are below. Instructions for Windows are in the section that follows. +# Before you build the client + +To actually use Deephaven, for example running these examples and unit +tests, you will eventually need to have a server running. If you have +an existing server running Deephaven Core, you should be able to +connect to that. However, if you don't have one, you can follow the +instructions here: https://deephaven.io/core/docs/how-to-guides/launch-build/. + +Note that it is only possible to build a server on Linux. Building a server on +Windows is not currently supported. + +You can build and install client libraries, tests, and examples +without having a server installed. However you will eventually need to +connect a server when you want to run them. + # Building the C++ client on Ubuntu 22.04 1. Start with an Ubuntu 22.04 install -2. Get Deephaven running by following the instructions here: https://deephaven.io/core/docs/how-to-guides/launch-build/ - -3. Get build tools +2. Get build tools ``` sudo apt update sudo apt install curl git g++ cmake make build-essential zlib1g-dev libbz2-dev libssl-dev pkg-config @@ -25,7 +38,7 @@ that follows. See the notes at the end of this document if you need the equivalent packages for Fedora. -4. Make a new directory for the Deephaven source code and assign that directory +3. Make a new directory for the Deephaven source code and assign that directory to a temporary shell variable. This will make subsequent build steps easier. ``` export DHSRC=$HOME/src/deephaven @@ -33,13 +46,13 @@ that follows. cd $DHSRC ``` -5. Clone deephaven-core sources. +4. Clone deephaven-core sources. ``` cd $DHSRC git clone https://github.com/deephaven/deephaven-core.git ``` -6. Build and install dependencies for Deephaven C++ client. +5. Build and install dependencies for Deephaven C++ client. The `build-dependencies.sh` script in this directory downloads, builds and installs the dependent libraries @@ -100,7 +113,7 @@ that follows. `CMAKE_PREFIX_PATH`. This file is intended to be `source`'d from a shell where you plan to build the C++ client. -7. Build and install Deephaven C++ client. Running `build-dependencies.sh` should have +6. Build and install Deephaven C++ client. Running `build-dependencies.sh` should have created an `env.sh` file that we source below to set relevant environment variables for the build. @@ -132,7 +145,7 @@ that follows. VERBOSE=1 make -j$NCPUS install 2>&1 | tee make-install.log ``` -8. Run one Deephaven example which uses the installed client. +7. Run one Deephaven example which uses the installed client. This is a smoke test that the basic functionality is working end to end, and the build is properly configured. Note this assumes Deephaven server is running (see step 2), @@ -144,7 +157,7 @@ that follows. ./hello_world ``` -9. (Optional) run the unit tests +8. (Optional) run the unit tests This assumes the build created on step 7 is available in the same directory. ``` @@ -153,25 +166,25 @@ that follows. ./tests ``` -10. Building in different distributions or with older toolchains. - While we don't support other linux distributions or GCC versions earlier - than 11, this section provides some notes that may help you - in that situation. - - * GCC 8 mixed with older versions of GNU as/binutils may fail to compile - `roaring.c` with an error similar to: - ``` - /tmp/cczCvQKd.s: Assembler messages: - /tmp/cczCvQKd.s:45826: Error: no such instruction: `vpcompressb %zmm0,%zmm1{%k2}' - /tmp/cczCvQKd.s:46092: Error: no such instruction: `vpcompressb %zmm0,%zmm1{%k1}' - ``` - In that case, add `-DCMAKE_C_FLAGS=-DCROARING_COMPILER_SUPPORTS_AVX512=0` - to the list of arguments to `cmake`. - - * Some platforms combining old versions of GCC and cmake may fail - to set the cmake C++ standard to 17 without explicitly adding - `-DCMAKE_CXX_STANDARD=17` to the list of arguments to `cmake`. - Note the default mode for C++ is `-std=gnu++17` for GCC 11. +9. Building in different distributions or with older toolchains. + While we don't support other linux distributions or GCC versions earlier + than 11, this section provides some notes that may help you + in that situation. + + * GCC 8 mixed with older versions of GNU as/binutils may fail to compile + `roaring.c` with an error similar to: + ``` + /tmp/cczCvQKd.s: Assembler messages: + /tmp/cczCvQKd.s:45826: Error: no such instruction: `vpcompressb %zmm0,%zmm1{%k2}' + /tmp/cczCvQKd.s:46092: Error: no such instruction: `vpcompressb %zmm0,%zmm1{%k1}' + ``` + In that case, add `-DCMAKE_C_FLAGS=-DCROARING_COMPILER_SUPPORTS_AVX512=0` + to the list of arguments to `cmake`. + + * Some platforms combining old versions of GCC and cmake may fail + to set the cmake C++ standard to 17 without explicitly adding + `-DCMAKE_CXX_STANDARD=17` to the list of arguments to `cmake`. + Note the default mode for C++ is `-std=gnu++17` for GCC 11. Notes (1) The standard assumptions for `Debug` and `Release` apply here. @@ -207,27 +220,23 @@ Notes # Building the C++ client on Windows 10 / Windows 11 -1. Get Deephaven running by following the instructions here: - - https://deephaven.io/core/docs/how-to-guides/launch-build/ - -2. Install Visual Studio 2022 Community Edition (or Professional, or Enterprise) +1. Install Visual Studio 2022 Community Edition (or Professional, or Enterprise) from here: https://visualstudio.microsoft.com/downloads/ When the installer runs, select the workload "Desktop development with C++" -3. Use your preferred version of git, or install Git from here: +2. Use your preferred version of git, or install Git from here: https://git-scm.com/download/win -4. We will do the actual build process inside a Visual Studio developer +3. We will do the actual build process inside a Visual Studio developer command prompt. Run the developer command prompt by navigating here: Start -> V -> Visual Studio 2022 -> Developer Command Prompt for VS 2022 -5. Make a 'dhsrc' directory that will hold the two repositories: the vcpkg +4. Make a 'dhsrc' directory that will hold the two repositories: the vcpkg package manager and Deephaven Core. Then make a 'dhinstall' directory that will hold the libraries and executables that are the result of this build process. @@ -236,7 +245,7 @@ Notes mkdir %HOMEDRIVE%%HOMEPATH%\dhinstall ``` -6. Use git to clone the two repositories mentioned above. +5. Use git to clone the two repositories mentioned above. If you are using Git for Windows, you can run the "Git Bash Shell" and type these commands into it: ``` @@ -245,7 +254,7 @@ Notes git clone https://github.com/deephaven/deephaven-core.git ``` -7. Come back to the Visual Studio developer command prompt and do the +6. Come back to the Visual Studio developer command prompt and do the one-time installation steps for vcpkg. Do not forget to set VCPKG_ROOT, as our build scripts rely on it being set correctly. ``` @@ -254,24 +263,24 @@ Notes set VCPKG_ROOT=%HOMEDRIVE%%HOMEPATH%\dhsrc\vcpkg ``` -8. Change to the Deephaven core directory and build/install the dependent +7. Change to the Deephaven core directory and build/install the dependent packages. On my computer this process took about 20 minutes. ``` cd /d %HOMEDRIVE%%HOMEPATH%\dhsrc\deephaven-core\cpp-client\deephaven %VCPKG_ROOT%\vcpkg.exe install --triplet x64-windows ``` -9. Now configure the build for Deephaven Core: +8. Now configure the build for Deephaven Core: ``` - cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake -DCMAKE_INSTALL_PREFIX=%HOMEDRIVE%%HOMEPATH%/dhinstall -DX_VCPKG_APPLOCAL_DEPS_INSTALL=ON + cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=%VCPKG_ROOT%/scripts/buildsystems/vcpkg.cmake -DCMAKE_INSTALL_PREFIX=%HOMEDRIVE%%HOMEPATH%/dhinstall -DX_VCPKG_APPLOCAL_DEPS_INSTALL=ON -DCMAKE_BUILD_TYPE=RelWithDebInfo ``` -10. Finally, build and install Deephaven Core: - ``` - cmake --build build --target install - ``` +9. Finally, build and install Deephaven Core: + ``` + cmake --build build --target install + ``` -11. Run the tests. +10. Run the tests. First, make sure Deephaven is running. If your Deephaven instance is running somewhere other than the default location of localhost:10000, then set these environment variables appropriately: diff --git a/cpp-client/build.gradle b/cpp-client/build.gradle index a615c404721..fc40076144f 100644 --- a/cpp-client/build.gradle +++ b/cpp-client/build.gradle @@ -68,6 +68,7 @@ def buildCppClientImage = Docker.registerDockerTask(project, 'cppClient') { include 'cpp-tests-to-junit.sh' include 'build-dependencies.sh' include 'deephaven/CMakeLists.txt' + include 'deephaven/cmake/**' include 'deephaven/dhcore/**' include 'deephaven/dhclient/**' include 'deephaven/examples/**' @@ -87,6 +88,7 @@ def buildCppClientImage = Docker.registerDockerTask(project, 'cppClient') { ${prefix}/log """) copyFile('deephaven/CMakeLists.txt', "${prefix}/src/deephaven/") + copyFile('deephaven/cmake/', "${prefix}/src/deephaven/cmake/") copyFile('deephaven/dhcore/', "${prefix}/src/deephaven/dhcore/") copyFile('deephaven/dhclient/', "${prefix}/src/deephaven/dhclient/") copyFile('deephaven/examples/', "${prefix}/src/deephaven/examples/") diff --git a/cpp-client/deephaven/CMakeLists.txt b/cpp-client/deephaven/CMakeLists.txt index 9cfc70db45a..2c8be6d3a3d 100644 --- a/cpp-client/deephaven/CMakeLists.txt +++ b/cpp-client/deephaven/CMakeLists.txt @@ -8,6 +8,7 @@ endif() project(deephaven) +set(deephaven_VERSION 0.36.0) set(CMAKE_CXX_STANDARD 17) # for CMAKE_INSTALL_{dir} @@ -40,15 +41,46 @@ if(NOT DHCORE_ONLY) ) install(TARGETS dhclient dhcore dhcore_static dhclient_tests - EXPORT deephavenConfig + EXPORT deephavenTargets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} ) - install(EXPORT deephavenConfig - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/deephaven + include(CMakePackageConfigHelpers) + write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/deephaven/deephavenConfigVersion.cmake" + VERSION ${deephaven_VERSION} + COMPATIBILITY AnyNewerVersion + ) + + export(EXPORT deephavenTargets + FILE "${CMAKE_CURRENT_BINARY_DIR}/deephaven/deephavenTargets.cmake" NAMESPACE deephaven:: ) + configure_file(cmake/deephavenConfig.cmake + "${CMAKE_CURRENT_BINARY_DIR}/deephaven/deephavenConfig.cmake" + COPYONLY + ) + + set(ConfigPackageLocation ${CMAKE_INSTALL_LIBDIR}/cmake/deephaven) + install(EXPORT deephavenTargets + FILE + deephavenTargets.cmake + NAMESPACE + deephaven:: + DESTINATION + ${ConfigPackageLocation} + ) + install( + FILES + cmake/deephavenConfig.cmake + "${CMAKE_CURRENT_BINARY_DIR}/deephaven/deephavenConfigVersion.cmake" + DESTINATION + ${ConfigPackageLocation} + COMPONENT + Devel + ) + endif() diff --git a/cpp-client/deephaven/cmake/deephavenConfig.cmake b/cpp-client/deephaven/cmake/deephavenConfig.cmake new file mode 100644 index 00000000000..88aa04e9744 --- /dev/null +++ b/cpp-client/deephaven/cmake/deephavenConfig.cmake @@ -0,0 +1,9 @@ +include(CMakeFindDependencyMacro) +find_dependency(Arrow 16.0.0) +find_dependency(ArrowFlight 16.0.0) +find_dependency(Immer) +find_dependency(Protobuf) +find_dependency(gRPC 1.63.0) +find_dependency(Threads) + +include("${CMAKE_CURRENT_LIST_DIR}/deephavenTargets.cmake") diff --git a/cpp-client/deephaven/dhclient/CMakeLists.txt b/cpp-client/deephaven/dhclient/CMakeLists.txt index a9e510a4f61..48d530f206c 100644 --- a/cpp-client/deephaven/dhclient/CMakeLists.txt +++ b/cpp-client/deephaven/dhclient/CMakeLists.txt @@ -8,7 +8,7 @@ include(GNUInstallDirs) find_package(Arrow CONFIG REQUIRED) find_package(ArrowFlight CONFIG REQUIRED HINTS ${Arrow_DIR}) -find_package(Immer REQUIRED) +find_package(Immer CONFIG REQUIRED) find_package(Protobuf CONFIG REQUIRED) find_package(gRPC CONFIG REQUIRED) find_package(Threads REQUIRED) @@ -44,6 +44,13 @@ set(ALL_FILES include/public/deephaven/client/flight.h include/public/deephaven/client/update_by.h + src/interop/client_interop.cc + src/interop/client_options_interop.cc + src/interop/update_by_interop.cc + include/public/deephaven/client/interop/client_interop.h + include/public/deephaven/client/interop/client_options_interop.h + include/public/deephaven/client/interop/update_by_interop.h + src/subscription/subscribe_thread.cc include/private/deephaven/client/subscription/subscribe_thread.h @@ -126,7 +133,6 @@ target_link_libraries(dhclient PUBLIC deephaven::dhcore) target_link_libraries(dhclient PUBLIC ArrowFlight::arrow_flight_shared) target_link_libraries(dhclient PUBLIC Arrow::arrow_shared) -target_link_libraries(dhclient PUBLIC immer) -target_link_libraries(dhclient PUBLIC protobuf::libprotobuf) -target_link_libraries(dhclient PUBLIC gRPC::grpc++) -target_link_libraries(dhclient PUBLIC Threads::Threads) +target_link_libraries(dhclient PRIVATE protobuf::libprotobuf) +target_link_libraries(dhclient PRIVATE gRPC::grpc++) +target_link_libraries(dhclient PRIVATE Threads::Threads) diff --git a/cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/client_interop.h b/cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/client_interop.h new file mode 100644 index 00000000000..e87ad5e6425 --- /dev/null +++ b/cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/client_interop.h @@ -0,0 +1,678 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#include +#include "deephaven/client/client.h" +#include "deephaven/client/client_options.h" +#include "deephaven/client/utility/table_maker.h" +#include "deephaven/dhcore/interop/interop_util.h" + + +namespace deephaven::client::interop { +/** + * A thin wrapper about std::shared_ptr. Not really necessary but + * makes it easier for humans to map to the corresponding class on the C# side. + */ +struct ArrowTableSpWrapper { +public: + explicit ArrowTableSpWrapper(std::shared_ptr table) : table_(std::move(table)) {} + std::shared_ptr table_; +}; + +/** + * This class exists so we don't get confused about what we are passing + * back and forth to .NET. Basically, like any other object, we need to + * heap-allocate this object and pass an opaque pointer back and forth + * to .NET. The fact that this object's only member is a shared pointer + * is irrelevant in terms of what we need to do. + */ +struct ClientTableSpWrapper { + using ClientTable = deephaven::dhcore::clienttable::ClientTable; +public: + explicit ClientTableSpWrapper(std::shared_ptr table) : table_(std::move(table)) {} + std::shared_ptr table_; +}; +} // namespace deephaven::client::interop { + +extern "C" { +void deephaven_client_TableHandleManager_dtor( + deephaven::dhcore::interop::NativePtr self); + +void deephaven_client_TableHandleManager_EmptyTable( + deephaven::dhcore::interop::NativePtr self, + int64_t size, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandleManager_FetchTable( + deephaven::dhcore::interop::NativePtr self, + const char *table_name, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandleManager_TimeTable( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr period, + deephaven::dhcore::interop::NativePtr start_time, + deephaven::dhcore::interop::InteropBool blink_table, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandleManager_InputTable( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr initial_table, + const char **key_columns, int32_t num_key_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandleManager_RunScript( + deephaven::dhcore::interop::NativePtr self, + const char *code, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_Client_Connect(const char *target, + deephaven::dhcore::interop::NativePtr options, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_Client_dtor( + deephaven::dhcore::interop::NativePtr self); + +void deephaven_client_Client_Close( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_Client_GetManager( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_GetAttributes( + deephaven::dhcore::interop::NativePtr self, + int32_t *num_columns, int64_t *num_rows, + deephaven::dhcore::interop::InteropBool *is_static, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_GetSchema( + deephaven::dhcore::interop::NativePtr self, + int32_t num_columns, + deephaven::dhcore::interop::StringHandle *columns, int32_t *column_types, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_dtor( + deephaven::dhcore::interop::NativePtr self); + +void deephaven_client_TableHandle_GetManager( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Where( + deephaven::dhcore::interop::NativePtr self, + const char *condition, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Ungroup( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::InteropBool null_fill, + const char **group_by_columns, int32_t num_group_by_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Sort( + deephaven::dhcore::interop::NativePtr self, + const char **columns, + const deephaven::dhcore::interop::InteropBool *ascendings, + const deephaven::dhcore::interop::InteropBool *abss, + int32_t num_sort_pairs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Select( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_SelectDistinct( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_View( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_DropColumns( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Update( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_LazyUpdate( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_LastBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Head( + deephaven::dhcore::interop::NativePtr self, + int64_t num_rows, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Tail( + deephaven::dhcore::interop::NativePtr self, + int64_t num_rows, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Merge( + deephaven::dhcore::interop::NativePtr self, + const char *key_column, + deephaven::dhcore::interop::NativePtr *sources, + int32_t num_sources, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_CrossJoin( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_NaturalJoin( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_LeftOuterJoin( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_ExactJoin( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Aj( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Raj( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_UpdateBy( + deephaven::dhcore::interop::NativePtr self, + const deephaven::dhcore::interop::NativePtr *ops, + int32_t num_ops, + const char **by, int32_t num_by, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_WhereIn( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr filter_table, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_AddTable( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr table_to_add, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_RemoveTable( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr table_to_remove, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_By( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr aggregate_combo, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_MinBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_MaxBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_SumBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_AbsSumBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_VarBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_StdBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_AvgBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_LastBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_FirstBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_MedianBy( + deephaven::dhcore::interop::NativePtr self, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_PercentileBy( + deephaven::dhcore::interop::NativePtr self, + double percentile, deephaven::dhcore::interop::InteropBool avg_median, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_CountBy( + deephaven::dhcore::interop::NativePtr self, + const char *weightColumn, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_WavgBy( + deephaven::dhcore::interop::NativePtr self, + const char *weightColumn, + const char **column_specs, int32_t num_column_specs, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_BindToVariable( + deephaven::dhcore::interop::NativePtr self, + const char *variable, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_ToClientTable( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr *client_table, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_ToString( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::InteropBool want_headers, + deephaven::dhcore::interop::StringHandle *result_handle, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_ToArrowTable( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +using NativeOnUpdate = void( + deephaven::dhcore::interop::NativePtr ticking_update); +using NativeOnFailure = void(deephaven::dhcore::interop::StringHandle, + deephaven::dhcore::interop::StringPoolHandle); + +void deephaven_client_TableHandle_Subscribe( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr native_on_update, + deephaven::dhcore::interop::NativePtr native_on_failure, + deephaven::dhcore::interop::NativePtr> *native_subscription_handle, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TableHandle_Unsubscribe( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr> native_subscription_handle, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_SubscriptionHandle_dtor( + deephaven::dhcore::interop::NativePtr> self); + +void deephaven_client_ArrowTable_dtor( + deephaven::dhcore::interop::NativePtr self); + +void deephaven_client_ArrowTable_GetDimensions( + deephaven::dhcore::interop::NativePtr self, + int32_t *num_columns, int64_t *num_rows, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_ArrowTable_GetSchema( + deephaven::dhcore::interop::NativePtr self, + int32_t num_columns, + deephaven::dhcore::interop::StringHandle *column_handles, int32_t *column_types, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_ClientTable_dtor( + deephaven::dhcore::interop::NativePtr self); + +void deephaven_client_ClientTable_GetDimensions( + deephaven::dhcore::interop::NativePtr self, + int32_t *num_columns, int64_t *num_rows, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_ClientTable_Schema( + deephaven::dhcore::interop::NativePtr self, + int32_t num_columns, + deephaven::dhcore::interop::StringHandle *column_handles, + int32_t *column_types, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_ClientTable_ToString( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::InteropBool want_headers, + deephaven::dhcore::interop::InteropBool want_row_numbers, + deephaven::dhcore::interop::StringHandle *text_handle, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_ClientTableHelper_GetInt8Column( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, int8_t *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientTableHelper_GetInt16Column( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, int16_t *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientTableHelper_GetInt32Column( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, int32_t *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientTableHelper_GetInt64Column( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, int64_t *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientTableHelper_GetFloatColumn( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, float *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientTableHelper_GetDoubleColumn( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, double *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, + int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientTableHelper_GetCharAsInt16Column( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, int16_t *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, + int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientTableHelper_GetBooleanAsInteropBoolColumn( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, int8_t *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientTableHelper_GetStringColumn( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, deephaven::dhcore::interop::StringHandle *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientTableHelper_GetDateTimeAsInt64Column( + deephaven::dhcore::interop::NativePtr self, + int32_t column_index, int64_t *data, + deephaven::dhcore::interop::InteropBool *optional_dest_null_flags, int64_t num_rows, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_TickingUpdate_dtor( + deephaven::dhcore::interop::NativePtr self); + +void deephaven_client_TickingUpdate_Current( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_AggregateCombo_Create( + const deephaven::dhcore::interop::NativePtr *aggregate_ptrs, + int32_t num_aggregates, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_AggregateCombo_dtor( + deephaven::dhcore::interop::NativePtr self); + +void deephaven_client_Aggregate_dtor( + deephaven::dhcore::interop::NativePtr self); +void deephaven_client_Aggregate_AbsSum( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Group( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Avg( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Count( + const char *column, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_First( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Last( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Max( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Med( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Min( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Pct( + double percentile, deephaven::dhcore::interop::InteropBool avg_median, + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Std( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Sum( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_Var( + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_Aggregate_WAvg(const char *weight, + const char **columns, int32_t num_columns, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); + +void deephaven_client_utility_DurationSpecifier_ctor_nanos( + int64_t nanos, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_utility_DurationSpecifier_ctor_durationstr( + const char *duration_str, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_utility_DurationSpecifier_dtor( + deephaven::dhcore::interop::NativePtr result); + +void deephaven_client_utility_TimePointSpecifier_ctor_nanos( + int64_t nanos, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_utility_TimePointSpecifier_ctor_timepointstr( + const char *time_point_str, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_utility_TimePointSpecifier_dtor( + deephaven::dhcore::interop::NativePtr result); + +void deephaven_dhclient_utility_TableMaker_ctor( + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_dtor( + deephaven::dhcore::interop::NativePtr self); +void deephaven_dhclient_utility_TableMaker_MakeTable( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::NativePtr manager, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__CharAsInt16( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const int16_t *data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__Int8( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const int8_t *data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__Int16( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const int16_t *data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__Int32( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const int32_t *data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__Int64( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const int64_t *data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__Float( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const float *data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__Double( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const double *data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__BoolAsInteropBool( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const int8_t *data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__String( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const char **data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_dhclient_utility_TableMaker_AddColumn__DateTimeAsInt64( + deephaven::dhcore::interop::NativePtr self, + const char *name, + const int64_t *data, + int32_t length, + const deephaven::dhcore::interop::InteropBool *optional_nulls, + deephaven::dhcore::interop::ErrorStatus *status); +} // extern "C" diff --git a/cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/client_options_interop.h b/cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/client_options_interop.h new file mode 100644 index 00000000000..033ddd0c720 --- /dev/null +++ b/cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/client_options_interop.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#include +#include "deephaven/client/client_options.h" +#include "deephaven/dhcore/interop/interop_util.h" + +extern "C" { +void deephaven_client_ClientOptions_ctor( + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_dtor( + deephaven::dhcore::interop::NativePtr self); +void deephaven_client_ClientOptions_SetDefaultAuthentication( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_SetBasicAuthentication( + deephaven::dhcore::interop::NativePtr self, + const char *username, const char *password, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_SetCustomAuthentication( + deephaven::dhcore::interop::NativePtr self, + const char *authentication_key, const char *authentication_value, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_SetSessionType( + deephaven::dhcore::interop::NativePtr self, + const char *session_type, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_SetUseTls( + deephaven::dhcore::interop::NativePtr self, + deephaven::dhcore::interop::InteropBool use_tls, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_SetTlsRootCerts( + deephaven::dhcore::interop::NativePtr self, + const char *tls_root_certs, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_SetClientCertChain( + deephaven::dhcore::interop::NativePtr self, + const char *client_cert_chain, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_SetClientPrivateKey( + deephaven::dhcore::interop::NativePtr self, + const char *client_private_key, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_AddIntOption( + deephaven::dhcore::interop::NativePtr self, + const char *opt, int32_t val, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_AddStringOption( + deephaven::dhcore::interop::NativePtr self, + const char *opt, const char *val, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_ClientOptions_AddExtraHeader( + deephaven::dhcore::interop::NativePtr self, + const char *header_name, const char *header_value, + deephaven::dhcore::interop::ErrorStatus *status); +} // extern "C" diff --git a/cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/update_by_interop.h b/cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/update_by_interop.h new file mode 100644 index 00000000000..660f3f9b62f --- /dev/null +++ b/cpp-client/deephaven/dhclient/include/public/deephaven/client/interop/update_by_interop.h @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#include +#include "deephaven/client/client.h" +#include "deephaven/client/client_options.h" +#include "deephaven/client/update_by.h" +#include "deephaven/client/utility/table_maker.h" +#include "deephaven/dhcore/interop/interop_util.h" + + +extern "C" { +void deephaven_client_UpdateByOperation_dtor( + deephaven::dhcore::interop::NativePtr self); +void deephaven_client_update_by_cumSum( + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_cumProd( + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_cumMin( + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_cumMax( + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_forwardFill( + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_delta( + const char **cols, int32_t num_cols, + deephaven::client::update_by::DeltaControl delta_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emaTick(double decay_ticks, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emaTime(const char *timestamp_col, + deephaven::dhcore::interop::NativePtr decay_time, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emsTick(double decay_ticks, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emsTime(const char *timestamp_col, + deephaven::dhcore::interop::NativePtr decay_time, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emminTick(double decay_ticks, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emminTime(const char *timestamp_col, + deephaven::dhcore::interop::NativePtr decay_time, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emmaxTick(double decay_ticks, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emmaxTime(const char *timestamp_col, + deephaven::dhcore::interop::NativePtr decay_time, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emstdTick(double decay_ticks, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_emstdTime(const char *timestamp_col, + deephaven::dhcore::interop::NativePtr decay_time, + const char **cols, int32_t num_cols, + const deephaven::client::update_by::OperationControl *op_control, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingSumTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingSumTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr rev_time, + deephaven::dhcore::interop::NativePtr fwd_time, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingGroupTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingGroupTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr rev_time, + deephaven::dhcore::interop::NativePtr fwd_time, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingAvgTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingAvgTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr rev_time, + deephaven::dhcore::interop::NativePtr fwd_time, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingMinTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingMinTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr rev_time, + deephaven::dhcore::interop::NativePtr fwd_time, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingMaxTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingMaxTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr rev_time, + deephaven::dhcore::interop::NativePtr fwd_time, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingProdTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingProdTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr rev_time, + deephaven::dhcore::interop::NativePtr fwd_time, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingCountTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingCountTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr rev_time, + deephaven::dhcore::interop::NativePtr fwd_time, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingStdTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingStdTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr rev_time, + deephaven::dhcore::interop::NativePtr fwd_time, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingWavgTick(const char *weight_col, + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +void deephaven_client_update_by_rollingWavgTime(const char *timestamp_col, + const char *weight_col, + const char **cols, int32_t num_cols, + deephaven::dhcore::interop::NativePtr rev_time, + deephaven::dhcore::interop::NativePtr fwd_time, + deephaven::dhcore::interop::NativePtr *result, + deephaven::dhcore::interop::ErrorStatus *status); +} // extern "C" diff --git a/cpp-client/deephaven/dhclient/include/public/deephaven/client/update_by.h b/cpp-client/deephaven/dhclient/include/public/deephaven/client/update_by.h index 9c9b8a96d56..07a1bc1962c 100644 --- a/cpp-client/deephaven/dhclient/include/public/deephaven/client/update_by.h +++ b/cpp-client/deephaven/dhclient/include/public/deephaven/client/update_by.h @@ -60,15 +60,15 @@ namespace deephaven::client::update_by { * This enum is meant to be a parallel of the Java enum java.math.MathContext. * See https://docs.oracle.com/javase/8/docs/api/java/math/MathContext.html */ -enum class MathContext { +enum class MathContext : int32_t { kUnlimited, kDecimal32, kDecimal64, kDecimal128 }; -enum class BadDataBehavior { +enum class BadDataBehavior : int32_t { kReset, kSkip, kThrow, kPoison }; -enum class DeltaControl { +enum class DeltaControl : int32_t { kNullDominates, kValueDominates, kZeroDominates }; diff --git a/cpp-client/deephaven/dhclient/include/public/deephaven/client/utility/table_maker.h b/cpp-client/deephaven/dhclient/include/public/deephaven/client/utility/table_maker.h index 5d89f846bf9..30dc3c365e1 100644 --- a/cpp-client/deephaven/dhclient/include/public/deephaven/client/utility/table_maker.h +++ b/cpp-client/deephaven/dhclient/include/public/deephaven/client/utility/table_maker.h @@ -30,6 +30,11 @@ class TypeConverter { [[nodiscard]] static TypeConverter CreateNew(const std::vector &values); + template + [[nodiscard]] + static TypeConverter CreateNew(const GetValue &get_value, const IsNull &is_null, + size_t size); + TypeConverter(std::shared_ptr data_type, std::string deephaven_type, std::shared_ptr column); ~TypeConverter(); @@ -107,6 +112,13 @@ class TableMaker { template void AddColumn(std::string name, const std::vector &values); + template + void AddColumn(std::string name, const std::vector> &values); + + template + void AddColumn(std::string name, const GetValue &get_value, const IsNull &is_null, + size_t size); + /** * Make the table. Call this after all your calls to AddColumn(). * @param manager The TableHandleManager @@ -129,7 +141,7 @@ struct TypeConverterTraits { // The below assert fires when this class is instantiated; i.e. when none of the specializations // match. It needs to be written this way (with "is_same") because for technical reasons it // needso be dependent on T, even if degenerately so. - static_assert(!std::is_same::value, "TableMaker doesn't know how to work with this type"); + static_assert(!std::is_same_v, "TableMaker doesn't know how to work with this type"); }; // Implementation note: GetDeephavenTypeName() is better as a function rather than a constant, @@ -137,8 +149,15 @@ struct TypeConverterTraits { template<> struct TypeConverterTraits { - using arrowType_t = arrow::UInt16Type; - using arrowBuilder_t = arrow::UInt16Builder; + static std::shared_ptr GetDataType() { + return std::make_shared(); + } + static arrow::UInt16Builder GetBuilder() { + return arrow::UInt16Builder(); + } + static char16_t Reinterpret(char16_t o) { + return o; + } static std::string_view GetDeephavenTypeName() { return "char"; } @@ -146,8 +165,15 @@ struct TypeConverterTraits { template<> struct TypeConverterTraits { - using arrowType_t = arrow::BooleanType; - using arrowBuilder_t = arrow::BooleanBuilder; + static std::shared_ptr GetDataType() { + return std::make_shared(); + } + static arrow::BooleanBuilder GetBuilder() { + return arrow::BooleanBuilder(); + } + static bool Reinterpret(bool o) { + return o; + } static std::string_view GetDeephavenTypeName() { return "java.lang.Boolean"; } @@ -155,8 +181,15 @@ struct TypeConverterTraits { template<> struct TypeConverterTraits { - using arrowType_t = arrow::Int8Type; - using arrowBuilder_t = arrow::Int8Builder; + static std::shared_ptr GetDataType() { + return std::make_shared(); + } + static arrow::Int8Builder GetBuilder() { + return arrow::Int8Builder(); + } + static int8_t Reinterpret(int8_t o) { + return o; + } static std::string_view GetDeephavenTypeName() { return "byte"; } @@ -164,8 +197,15 @@ struct TypeConverterTraits { template<> struct TypeConverterTraits { - using arrowType_t = arrow::Int16Type; - using arrowBuilder_t = arrow::Int16Builder; + static std::shared_ptr GetDataType() { + return std::make_shared(); + } + static arrow::Int16Builder GetBuilder() { + return arrow::Int16Builder(); + } + static int16_t Reinterpret(int16_t o) { + return o; + } static std::string_view GetDeephavenTypeName() { return "short"; } @@ -173,8 +213,15 @@ struct TypeConverterTraits { template<> struct TypeConverterTraits { - using arrowType_t = arrow::Int32Type; - using arrowBuilder_t = arrow::Int32Builder; + static std::shared_ptr GetDataType() { + return std::make_shared(); + } + static arrow::Int32Builder GetBuilder() { + return arrow::Int32Builder(); + } + static int32_t Reinterpret(int32_t o) { + return o; + } static std::string_view GetDeephavenTypeName() { return "int"; } @@ -182,8 +229,15 @@ struct TypeConverterTraits { template<> struct TypeConverterTraits { - using arrowType_t = arrow::Int64Type; - using arrowBuilder_t = arrow::Int64Builder; + static std::shared_ptr GetDataType() { + return std::make_shared(); + } + static arrow::Int64Builder GetBuilder() { + return arrow::Int64Builder(); + } + static int64_t Reinterpret(int64_t o) { + return o; + } static std::string_view GetDeephavenTypeName() { return "long"; } @@ -191,8 +245,15 @@ struct TypeConverterTraits { template<> struct TypeConverterTraits { - using arrowType_t = arrow::FloatType; - using arrowBuilder_t = arrow::FloatBuilder; + static std::shared_ptr GetDataType() { + return std::make_shared(); + } + static arrow::FloatBuilder GetBuilder() { + return arrow::FloatBuilder(); + } + static float Reinterpret(float o) { + return o; + } static std::string_view GetDeephavenTypeName() { return "float"; } @@ -200,8 +261,15 @@ struct TypeConverterTraits { template<> struct TypeConverterTraits { - using arrowType_t = arrow::DoubleType; - using arrowBuilder_t = arrow::DoubleBuilder; + static std::shared_ptr GetDataType() { + return std::make_shared(); + } + static arrow::DoubleBuilder GetBuilder() { + return arrow::DoubleBuilder(); + } + static double Reinterpret(double o) { + return o; + } static std::string_view GetDeephavenTypeName() { return "double"; } @@ -209,18 +277,48 @@ struct TypeConverterTraits { template<> struct TypeConverterTraits { - using arrowType_t = arrow::StringType; - using arrowBuilder_t = arrow::StringBuilder; + static std::shared_ptr GetDataType() { + return std::make_shared(); + } + static arrow::StringBuilder GetBuilder() { + return arrow::StringBuilder(); + } + static const std::string &Reinterpret(const std::string &o) { + return o; + } static std::string_view GetDeephavenTypeName() { return "java.lang.String"; } }; +template<> +struct TypeConverterTraits { + static std::shared_ptr GetDataType() { + return arrow::timestamp(arrow::TimeUnit::NANO, "UTC"); + } + static arrow::TimestampBuilder GetBuilder() { + return arrow::TimestampBuilder(GetDataType(), arrow::default_memory_pool()); + } + static int64_t Reinterpret(const deephaven::dhcore::DateTime &dt) { + return dt.Nanos(); + } + static std::string_view GetDeephavenTypeName() { + return "java.time.ZonedDateTime"; + } +}; + template struct TypeConverterTraits> { using inner_t = TypeConverterTraits; - using arrowType_t = typename inner_t::arrowType_t; - using arrowBuilder_t = typename inner_t::arrowBuilder_t; + static auto GetDataType() { + return inner_t::GetDataType(); + } + static auto GetBuilder() { + return inner_t::GetBuilder(); + } + static auto Reinterpret(const T &o) { + return inner_t::Reinterpret(o); + } static std::string_view GetDeephavenTypeName() { return TypeConverterTraits::GetDeephavenTypeName(); } @@ -232,14 +330,14 @@ TypeConverter TypeConverter::CreateNew(const std::vector &values) { typedef TypeConverterTraits traits_t; - auto data_type = std::make_shared(); + auto data_type = traits_t::GetDataType(); + auto builder = traits_t::GetBuilder(); - typename traits_t::arrowBuilder_t builder; for (const auto &value : values) { bool valid; const auto *contained_value = TryGetContainedValue(&value, &valid); if (valid) { - OkOrThrow(DEEPHAVEN_LOCATION_EXPR(builder.Append(*contained_value))); + OkOrThrow(DEEPHAVEN_LOCATION_EXPR(builder.Append(traits_t::Reinterpret(*contained_value)))); } else { OkOrThrow(DEEPHAVEN_LOCATION_EXPR(builder.AppendNull())); } @@ -254,20 +352,20 @@ TypeConverter TypeConverter::CreateNew(const std::vector &values) { std::move(array)); } -template<> -inline TypeConverter TypeConverter::CreateNew(const std::vector &values) { +template +TypeConverter TypeConverter::CreateNew(const GetValue &get_value, const IsNull &is_null, + size_t size) { using deephaven::client::utility::OkOrThrow; - // TODO(kosak): put somewhere - constexpr const char *kDeephavenTypeName = "java.time.ZonedDateTime"; + typedef TypeConverterTraits traits_t; - auto data_type = arrow::timestamp(arrow::TimeUnit::NANO, "UTC"); - arrow::TimestampBuilder builder(data_type, arrow::default_memory_pool()); - for (const auto &value : values) { - bool valid; - const auto *contained_value = TryGetContainedValue(&value, &valid); - if (valid) { - OkOrThrow(DEEPHAVEN_LOCATION_EXPR(builder.Append(contained_value->Nanos()))); + auto data_type = traits_t::GetDataType(); + auto builder = traits_t::GetBuilder(); + + for (size_t i = 0; i != size; ++i) { + if (!is_null(i)) { + OkOrThrow(DEEPHAVEN_LOCATION_EXPR( + builder.Append(traits_t::Reinterpret(get_value(i))))); } else { OkOrThrow(DEEPHAVEN_LOCATION_EXPR(builder.AppendNull())); } @@ -275,16 +373,35 @@ inline TypeConverter TypeConverter::CreateNew(const std::vector void TableMaker::AddColumn(std::string name, const std::vector &values) { - auto info = internal::TypeConverter::CreateNew(values); + // Specifying the return type here in this way (rather than const T &) + // allows us to deal with std::vector, which is very special, and would + // otherwise cause a compiler error, because of the way it is specialized. + auto get_value = [&](size_t index) -> typename std::vector::const_reference { return values[index]; }; + auto is_null = [](size_t /*index*/) { return false; }; + return AddColumn(std::move(name), get_value, is_null, values.size()); +} + +template +void TableMaker::AddColumn(std::string name, const std::vector> &values) { + auto get_value = [&](size_t index) -> const T& { return *values[index]; }; + auto is_null = [&](size_t index) { return !values[index].has_value(); }; + return AddColumn(std::move(name), get_value, is_null, values.size()); +} + +template +void TableMaker::AddColumn(std::string name, const GetValue &get_value, const IsNull &is_null, + size_t size) { + auto info = internal::TypeConverter::CreateNew(get_value, is_null, size); FinishAddColumn(std::move(name), std::move(info)); } } // namespace deephaven::client::utility diff --git a/cpp-client/deephaven/dhclient/src/interop/client_interop.cc b/cpp-client/deephaven/dhclient/src/interop/client_interop.cc new file mode 100644 index 00000000000..6b5a66d8e35 --- /dev/null +++ b/cpp-client/deephaven/dhclient/src/interop/client_interop.cc @@ -0,0 +1,1370 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#include "deephaven/client/interop/client_interop.h" + +#include +#include +#include +#include "deephaven/client/client.h" +#include "deephaven/client/client_options.h" +#include "deephaven/client/subscription/subscription_handle.h" +#include "deephaven/client/update_by.h" +#include "deephaven/client/utility/arrow_util.h" +#include "deephaven/client/utility/table_maker.h" +#include "deephaven/dhcore/interop/interop_util.h" +#include "deephaven/dhcore/utility/utility.h" +#include "deephaven/third_party/fmt/format.h" + +using deephaven::client::Aggregate; +using deephaven::client::AggregateCombo; +using deephaven::client::Client; +using deephaven::client::ClientOptions; +using deephaven::client::SortDirection; +using deephaven::client::SortPair; +using deephaven::client::TableHandle; +using deephaven::client::TableHandleManager; +using deephaven::client::UpdateByOperation; +using deephaven::client::subscription::SubscriptionHandle; +using deephaven::client::interop::ArrowTableSpWrapper; +using deephaven::client::utility::ArrowUtil; +using deephaven::client::interop::ClientTableSpWrapper; +using deephaven::client::utility::DurationSpecifier; +using deephaven::client::utility::TableMaker; +using deephaven::client::utility::TimePointSpecifier; +using deephaven::dhcore::DateTime; +using deephaven::dhcore::chunk::BooleanChunk; +using deephaven::dhcore::chunk::CharChunk; +using deephaven::dhcore::chunk::Chunk; +using deephaven::dhcore::chunk::DateTimeChunk; +using deephaven::dhcore::chunk::DoubleChunk; +using deephaven::dhcore::chunk::FloatChunk; +using deephaven::dhcore::chunk::Int8Chunk; +using deephaven::dhcore::chunk::Int16Chunk; +using deephaven::dhcore::chunk::Int32Chunk; +using deephaven::dhcore::chunk::Int64Chunk; +using deephaven::dhcore::chunk::StringChunk; +using deephaven::dhcore::interop::ErrorStatus; +using deephaven::dhcore::interop::InteropBool; +using deephaven::dhcore::interop::NativePtr; +using deephaven::dhcore::interop::StringHandle; +using deephaven::dhcore::interop::StringPoolBuilder; +using deephaven::dhcore::interop::StringPoolHandle; +using deephaven::dhcore::ticking::TickingCallback; +using deephaven::dhcore::ticking::TickingUpdate; +using deephaven::dhcore::utility::GetWhat; +using deephaven::dhcore::utility::MakeReservedVector; + +namespace { +void GetColumnHelper(ClientTableSpWrapper *self, + int32_t column_index, + Chunk *data_chunk, InteropBool *optional_dest_null_flags, int64_t num_rows) { + auto cs = self->table_->GetColumn(column_index); + std::unique_ptr null_data; + BooleanChunk null_chunk; + BooleanChunk *null_chunkp = nullptr; + if (optional_dest_null_flags != nullptr) { + null_data.reset(new bool[num_rows]); + null_chunk = BooleanChunk::CreateView(null_data.get(), num_rows); + null_chunkp = &null_chunk; + } + + auto rows = self->table_->GetRowSequence(); + cs->FillChunk(*rows, data_chunk, null_chunkp); + + if (optional_dest_null_flags != nullptr) { + for (int64_t i = 0; i != num_rows; ++i) { + optional_dest_null_flags[i] = InteropBool(null_data[i]); + } + } +} + +void JoinHelper( + NativePtr self, + NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + NativePtr *result, + ErrorStatus *status, + TableHandle (TableHandle::*invoker)(const TableHandle &, std::vector, + std::vector) const) { + status->Run([=]() { + std::vector cols_to_match(columns_to_match, + columns_to_match + num_columns_to_match); + std::vector cols_to_add(columns_to_add, + columns_to_add + num_columns_to_add); + auto table = (self->*invoker)(*right_side, std::move(cols_to_match), std::move(cols_to_add)); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void ByHelper( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status, + TableHandle (TableHandle::*invoker)(std::vector) const) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = (self->*invoker)(std::move(cols)); + result->Reset(new TableHandle(std::move(table))); + }); +} +} // namespace + +extern "C" { +// There is no TableHandleManager_ctor entry point because we don't need callers to invoke +// the TableHandleManager ctor directly. +void deephaven_client_TableHandleManager_dtor(NativePtr self) { + delete self.Get(); +} + +void deephaven_client_TableHandleManager_EmptyTable( + NativePtr self, + int64_t size, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto table = self->EmptyTable(size); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandleManager_FetchTable( + NativePtr self, + const char *table_name, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto table = self->FetchTable(table_name); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandleManager_TimeTable( + NativePtr self, + NativePtr period, + NativePtr start_time, + InteropBool blink_table, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto table = self->TimeTable(*period, *start_time, (bool)blink_table); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandleManager_InputTable( + NativePtr self, + NativePtr initial_table, + const char **key_columns, int32_t num_key_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector kcs(key_columns, key_columns + num_key_columns); + auto table = self->InputTable(*initial_table, std::move(kcs)); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandleManager_RunScript( + NativePtr self, + const char *code, + ErrorStatus *status) { + status->Run([self, code]() { + self->RunScript(code); + }); +} + +void deephaven_client_Client_Connect(const char *target, + NativePtr options, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto res = Client::Connect(target, *options); + result->Reset(new Client(std::move(res))); + }); +} + +// There is no Client_ctor entry point because we don't need callers to invoke +// the Client ctor directly. +void deephaven_client_Client_dtor(NativePtr self) { + delete self; +} + + +void deephaven_client_Client_Close(NativePtr self, + ErrorStatus *status) { + status->Run([=]() { + self->Close(); + }); +} + +void deephaven_client_Client_GetManager(NativePtr self, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto res = self->GetManager(); + result->Reset(new TableHandleManager(std::move(res))); + }); +} + +void deephaven_client_TableHandle_GetAttributes( + NativePtr self, + int32_t *num_columns, int64_t *num_rows, InteropBool *is_static, + ErrorStatus *status) { + status->Run([=]() { + *num_columns = self->Schema()->NumCols(); + *num_rows = self->NumRows(); + *is_static = (InteropBool)self->IsStatic(); + }); +} + +void deephaven_client_TableHandle_GetSchema( + NativePtr self, + int32_t num_columns, StringHandle *column_handles, int32_t *column_types, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + const auto &schema = self->Schema(); + + if (num_columns != schema->NumCols()) { + auto message = fmt::format("Expected {} columns, but schema has {}", + num_columns, schema->NumCols()); + throw std::runtime_error(message); + } + + StringPoolBuilder builder; + for (int32_t i = 0; i != num_columns; ++i) { + column_handles[i] = builder.Add(schema->Names()[i]); + column_types[i] = static_cast(schema->Types()[i]); + } + *string_pool_handle = builder.Build(); + }); +} + +// There is no TableHandle_ctor entry point because we don't need callers to invoke +// the TableHandle ctor directly. +void deephaven_client_TableHandle_dtor(NativePtr self) { + delete self.Get(); +} + +void deephaven_client_TableHandle_GetManager( + NativePtr self, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto manager = self->GetManager(); + result->Reset(new TableHandleManager(std::move(manager))); + }); +} + +void deephaven_client_TableHandle_Where( + NativePtr self, + const char *condition, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto table = self->Where(condition); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_Ungroup( + NativePtr self, + InteropBool null_fill, + const char **group_by_columns, int32_t num_group_by_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(group_by_columns, group_by_columns + num_group_by_columns); + auto table = self->Ungroup((bool)null_fill, std::move(cols)); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_Sort( + NativePtr self, + const char **columns, + const InteropBool *ascendings, + const InteropBool *abss, + int32_t num_sort_pairs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto sort_pairs = MakeReservedVector(num_sort_pairs); + for (int32_t i = 0; i != num_sort_pairs; ++i) { + sort_pairs.emplace_back( + columns[i], + ascendings[i] ? SortDirection::kAscending : SortDirection::kDescending, + (bool)abss[i]); + } + auto table = self->Sort(std::move(sort_pairs)); + result->Reset(new TableHandle(std::move(table))); + }); + +} + +void deephaven_client_TableHandle_Select( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->Select(cols); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_SelectDistinct( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->SelectDistinct(cols); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_View( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->View(cols); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_DropColumns( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->DropColumns(cols); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_Update( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->Update(cols); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_LazyUpdate( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->LazyUpdate(cols); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_MinBy( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + ByHelper(self, column_specs, num_column_specs, result, status, &TableHandle::MinBy); +} + +void deephaven_client_TableHandle_SumBy( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + ByHelper(self, column_specs, num_column_specs, result, status, &TableHandle::SumBy); +} + +void deephaven_client_TableHandle_AbsSumBy( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + ByHelper(self, column_specs, num_column_specs, result, status, &TableHandle::AbsSumBy); +} + +void deephaven_client_TableHandle_VarBy( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + ByHelper(self, column_specs, num_column_specs, result, status, &TableHandle::VarBy); +} + +void deephaven_client_TableHandle_StdBy( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + ByHelper(self, column_specs, num_column_specs, result, status, &TableHandle::StdBy); +} + +void deephaven_client_TableHandle_AvgBy( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + ByHelper(self, column_specs, num_column_specs, result, status, &TableHandle::AvgBy); +} + +void deephaven_client_TableHandle_LastBy( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + ByHelper(self, column_specs, num_column_specs, result, status, &TableHandle::LastBy); +} + +void deephaven_client_TableHandle_FirstBy( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + ByHelper(self, column_specs, num_column_specs, result, status, &TableHandle::FirstBy); +} + +void deephaven_client_TableHandle_MedianBy( + NativePtr self, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + ByHelper(self, column_specs, num_column_specs, result, status, &TableHandle::MedianBy); +} + +void deephaven_client_TableHandle_PercentileBy( + NativePtr self, + double percentile, deephaven::dhcore::interop::InteropBool avg_median, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->PercentileBy(percentile, (bool)avg_median, std::move(cols)); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_CountBy( + NativePtr self, + const char *weight_column, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->CountBy(weight_column, std::move(cols)); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_WavgBy( + NativePtr self, + const char *weight_column, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->WAvgBy(weight_column, std::move(cols)); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_WhereIn( + NativePtr self, + NativePtr filter_table, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->WhereIn(*filter_table, cols); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_CrossJoin( + NativePtr self, + NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + NativePtr *result, + ErrorStatus *status) { + JoinHelper(self, right_side, + columns_to_match, num_columns_to_match, + columns_to_add, num_columns_to_add, + result, status, + &TableHandle::CrossJoin); +} + +void deephaven_client_TableHandle_NaturalJoin( + NativePtr self, + NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + NativePtr *result, + ErrorStatus *status) { + JoinHelper(self, right_side, + columns_to_match, num_columns_to_match, + columns_to_add, num_columns_to_add, + result, status, + &TableHandle::NaturalJoin); +} + +void deephaven_client_TableHandle_LeftOuterJoin( + NativePtr self, + NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + NativePtr *result, + ErrorStatus *status) { + JoinHelper(self, right_side, + columns_to_match, num_columns_to_match, + columns_to_add, num_columns_to_add, + result, status, + &TableHandle::LeftOuterJoin); +} + +void deephaven_client_TableHandle_ExactJoin( + NativePtr self, + NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + NativePtr *result, + ErrorStatus *status) { + JoinHelper(self, right_side, + columns_to_match, num_columns_to_match, + columns_to_add, num_columns_to_add, + result, status, + &TableHandle::ExactJoin); +} + +void deephaven_client_TableHandle_Aj( + NativePtr self, + NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + NativePtr *result, + ErrorStatus *status) { + JoinHelper(self, right_side, + columns_to_match, num_columns_to_match, + columns_to_add, num_columns_to_add, + result, status, + &TableHandle::Aj); +} + +void deephaven_client_TableHandle_Raj( + NativePtr self, + NativePtr right_side, + const char **columns_to_match, int32_t num_columns_to_match, + const char **columns_to_add, int32_t num_columns_to_add, + NativePtr *result, + ErrorStatus *status) { + JoinHelper(self, right_side, + columns_to_match, num_columns_to_match, + columns_to_add, num_columns_to_add, + result, status, + &TableHandle::Raj); +} + +void deephaven_client_TableHandle_UpdateBy( + NativePtr self, + const NativePtr *ops, int32_t num_ops, + const char **by, int32_t num_by, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto ops_vec = MakeReservedVector(num_ops); + for (int32_t i = 0; i != num_ops; ++i) { + ops_vec.emplace_back(*ops[i].Get()); + } + std::vector by_vec(by, by + num_by); + auto res = self->UpdateBy(std::move(ops_vec), std::move(by_vec)); + result->Reset(new TableHandle(std::move(res))); + }); +} + +void deephaven_client_TableHandle_AddTable( + NativePtr self, + NativePtr table_to_add, + ErrorStatus *status) { + status->Run([=]() { + self->AddTable(*table_to_add); + }); +} + +void deephaven_client_TableHandle_RemoveTable( + NativePtr self, + NativePtr table_to_remove, + ErrorStatus *status) { + status->Run([=]() { + self->RemoveTable(*table_to_remove); + }); +} + +void deephaven_client_TableHandle_By( + NativePtr self, + NativePtr aggregate_combo, + const char **column_specs, int32_t num_column_specs, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector cols(column_specs, column_specs + num_column_specs); + auto table = self->By(*aggregate_combo, std::move(cols)); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_Head( + NativePtr self, + int64_t num_rows, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto table = self->Head(num_rows); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_Tail( + NativePtr self, + int64_t num_rows, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto table = self->Tail(num_rows); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_Merge(NativePtr self, + const char *key_column, + NativePtr *sources, int32_t num_sources, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + // We need to make copies of the passed-in TableHandles because we're not + // allowed to modify or move them. + auto sources_copy = MakeReservedVector(num_sources); + for (int32_t i = 0; i != num_sources; ++i) { + sources_copy.push_back(*sources[i]); + } + auto table = self->Merge(key_column, std::move(sources_copy)); + result->Reset(new TableHandle(std::move(table))); + }); +} + +void deephaven_client_TableHandle_BindToVariable( + NativePtr self, + const char *variable, + ErrorStatus *status) { + status->Run([=]() { + self->BindToVariable(variable); + }); +} + +void deephaven_client_TableHandle_ToString( + NativePtr self, + InteropBool want_headers, + StringHandle *result_handle, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + StringPoolBuilder builder; + *result_handle = builder.Add(self->ToString((bool)want_headers)); + *string_pool_handle = builder.Build(); + }); +} + +void deephaven_client_TableHandle_ToArrowTable( + NativePtr self, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto at = self->ToArrowTable(); + result->Reset(new ArrowTableSpWrapper(std::move(at))); + }); +} + +class WrappedTickingCallback final : public TickingCallback { +public: + WrappedTickingCallback(NativeOnUpdate *on_update, NativeOnFailure *on_failure) : + on_update_(on_update), on_failure_(on_failure) {} + + void OnTick(TickingUpdate update) final { + NativePtr nptr(new TickingUpdate(std::move(update))); + (*on_update_)(nptr); + } + + void OnFailure(std::exception_ptr eptr) final { + StringPoolBuilder builder; + auto string_handle = builder.Add(GetWhat(eptr)); + auto pool_handle = builder.Build(); + (*on_failure_)(string_handle, pool_handle); + } + +private: + NativeOnUpdate *on_update_ = nullptr; + NativeOnFailure *on_failure_ = nullptr; +}; + +void deephaven_client_TableHandle_Subscribe( + NativePtr self, + NativePtr native_on_update, + NativePtr native_on_failure, + NativePtr> *native_subscription_handle, + ErrorStatus *status) { + status->Run([=]() { + auto wtc = std::make_shared(native_on_update, native_on_failure); + auto handle = self->Subscribe(std::move(wtc)); + native_subscription_handle->Reset(new std::shared_ptr(std::move(handle))); + }); +} + +void deephaven_client_TableHandle_Unsubscribe( + NativePtr self, + NativePtr> native_subscription_handle, + ErrorStatus *status) { + status->Run([=]() { + self->Unsubscribe(*native_subscription_handle); + }); +} + +void deephaven_client_SubscriptionHandle_dtor( + deephaven::dhcore::interop::NativePtr> self) { + delete self.Get(); +} + +void deephaven_client_TableHandle_ToClientTable( + NativePtr self, + NativePtr *client_table, + ErrorStatus *status) { + status->Run([=]() { + auto ct = self->ToClientTable(); + client_table->Reset(new ClientTableSpWrapper(std::move(ct))); + }); +} + +void deephaven_client_ArrowTable_dtor( + NativePtr self) { + delete self.Get(); +} + +void deephaven_client_ArrowTable_GetDimensions( + NativePtr self, + int32_t *num_columns, int64_t *num_rows, + ErrorStatus *status) { + status->Run([=]() { + *num_columns = self->table_->num_columns(); + *num_rows = self->table_->num_rows(); + }); +} + +void deephaven_client_ArrowTable_GetSchema( + NativePtr self, + int32_t num_columns, StringHandle *column_handles, int32_t *column_types, + StringPoolHandle *string_pool_handle, ErrorStatus *status) { + status->Run([=]() { + const auto &schema = self->table_->schema(); + if (schema->num_fields() != num_columns) { + auto message = fmt::format("Expected schema->num_fields ({}) == num_columns ({})", + schema->num_fields(), num_columns); + throw std::runtime_error(DEEPHAVEN_LOCATION_STR(message)); + } + + StringPoolBuilder builder; + for (int32_t i = 0; i != num_columns; ++i) { + const auto &field = schema->fields()[i]; + column_handles[i] = builder.Add(field->name()); + auto element_type_id = *ArrowUtil::GetElementTypeId(*field->type(), true); + column_types[i] = static_cast(element_type_id); + } + *string_pool_handle = builder.Build(); + }); +} + +void deephaven_client_TickingUpdate_dtor(NativePtr self) { + delete self.Get(); +} + +void deephaven_client_TickingUpdate_Current(NativePtr self, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + result->Reset(new ClientTableSpWrapper(self->Current())); + }); +} + +void deephaven_client_ClientTable_GetDimensions( + NativePtr self, + int32_t *num_columns, int64_t *num_rows, + ErrorStatus *status) { + status->Run([=]() { + *num_columns = static_cast(self->table_->NumColumns()); + *num_rows = static_cast(self->table_->NumRows()); + }); +} + +void deephaven_client_ClientTable_Schema(NativePtr self, + int32_t num_columns, StringHandle *column_handles, int32_t *column_types, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + const auto &schema = self->table_->Schema(); + if (schema->NumCols() != num_columns) { + auto message = fmt::format("Expected schema->num_fields ({}) == num_columns ({})", + schema->NumCols(), num_columns); + throw std::runtime_error(DEEPHAVEN_LOCATION_STR(message)); + } + + StringPoolBuilder builder; + for (int32_t i = 0; i != num_columns; ++i) { + column_handles[i] = builder.Add(schema->Names()[i]); + column_types[i] = static_cast(schema->Types()[i]); + } + *string_pool_handle = builder.Build(); + }); +} + +void deephaven_client_ClientTable_ToString( + NativePtr self, + InteropBool want_headers, + InteropBool want_row_numbers, + StringHandle *text_handle, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + StringPoolBuilder builder; + auto text = self->table_->ToString((bool)want_headers, (bool)want_row_numbers); + *text_handle = builder.Add(text); + *string_pool_handle = builder.Build(); + }); +} + +void deephaven_client_ClientTable_dtor(NativePtr self) { + delete self.Get(); +} + +void deephaven_client_ClientTableHelper_GetInt8Column( + NativePtr self, + int32_t column_index, + int8_t *data, InteropBool *optional_dest_null_flags, int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + auto data_chunk = Int8Chunk::CreateView(data, num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + // return default StringPoolHandle because this type doesn't need a string pool + *string_pool_handle = StringPoolHandle(); + }); +} + +void deephaven_client_ClientTableHelper_GetInt16Column( + NativePtr self, + int32_t column_index, + int16_t *data, InteropBool *optional_dest_null_flags, int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + auto data_chunk = Int16Chunk::CreateView(data, num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + // return default StringPoolHandle because this type doesn't need a string pool + *string_pool_handle = StringPoolHandle(); + }); +} + +void deephaven_client_ClientTableHelper_GetInt32Column( + NativePtr self, + int32_t column_index, + int32_t *data, InteropBool *optional_dest_null_flags, int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + auto data_chunk = Int32Chunk::CreateView(data, num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + // return default StringPoolHandle because this type doesn't need a string pool + *string_pool_handle = StringPoolHandle(); + }); +} + +void deephaven_client_ClientTableHelper_GetInt64Column( + NativePtr self, + int32_t column_index, + int64_t *data, InteropBool *optional_dest_null_flags, int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + auto data_chunk = Int64Chunk::CreateView(data, num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + // return default StringPoolHandle because this type doesn't need a string pool + *string_pool_handle = StringPoolHandle(); + }); +} + +void deephaven_client_ClientTableHelper_GetFloatColumn( + NativePtr self, + int32_t column_index, float *data, InteropBool *optional_dest_null_flags, int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + auto data_chunk = FloatChunk::CreateView(data, num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + // return default StringPoolHandle because this type doesn't need a string pool + *string_pool_handle = StringPoolHandle(); + }); +} + +void deephaven_client_ClientTableHelper_GetDoubleColumn( + NativePtr self, + int32_t column_index, double *data, InteropBool *optional_dest_null_flags, int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + auto data_chunk = DoubleChunk::CreateView(data, num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + // return default StringPoolHandle because this type doesn't need a string pool + *string_pool_handle = StringPoolHandle(); + }); +} + +void deephaven_client_ClientTableHelper_GetCharAsInt16Column( + NativePtr self, + int32_t column_index, int16_t *data, InteropBool *optional_dest_null_flags, int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + auto data_chunk = CharChunk::Create(num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + // For char, boolean, DateTime, and String we have to do a little data conversion. + for (int64_t i = 0; i != num_rows; ++i) { + data[i] = static_cast(data_chunk.data()[i]); + } + // return default StringPoolHandle because this type doesn't need a string pool + *string_pool_handle = StringPoolHandle(); + }); +} + +void deephaven_client_ClientTableHelper_GetBooleanAsInteropBoolColumn( + NativePtr self, + int32_t column_index, int8_t *data, InteropBool *optional_dest_null_flags, int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + // For char, boolean, DateTime, and String we have to do a little data conversion. + auto data_chunk = BooleanChunk::Create(num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + for (int64_t i = 0; i != num_rows; ++i) { + data[i] = data_chunk.data()[i] ? 1 : 0; + } + // return default StringPoolHandle because this type doesn't need a string pool + *string_pool_handle = StringPoolHandle(); + }); +} + +void deephaven_client_ClientTableHelper_GetStringColumn( + NativePtr self, + int32_t column_index, StringHandle *data, InteropBool *optional_dest_null_flags, + int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + // For char, boolean, DateTime, and String we have to do a little data conversion. + auto data_chunk = StringChunk::Create(num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + StringPoolBuilder builder; + for (int64_t i = 0; i != num_rows; ++i) { + data[i] = builder.Add(data_chunk.data()[i]); + } + *string_pool_handle = builder.Build(); + }); +} + +void deephaven_client_ClientTableHelper_GetDateTimeAsInt64Column( + NativePtr self, + int32_t column_index, int64_t *data, InteropBool *optional_dest_null_flags, int64_t num_rows, + StringPoolHandle *string_pool_handle, + ErrorStatus *status) { + status->Run([=]() { + // For char, boolean, DateTime, and String we have to do a little data conversion. + auto data_chunk = DateTimeChunk::Create(num_rows); + GetColumnHelper(self, column_index, &data_chunk, optional_dest_null_flags, num_rows); + for (int64_t i = 0; i != num_rows; ++i) { + data[i] = data_chunk.data()[i].Nanos(); + } + // return default StringPoolHandle because this type doesn't need a string pool + *string_pool_handle = StringPoolHandle(); + }); +} + +void deephaven_client_AggregateCombo_Create( + const NativePtr *aggregate_ptrs, + int32_t num_aggregates, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto agg_copies = MakeReservedVector(num_aggregates); + for (int32_t i = 0; i != num_aggregates; ++i) { + agg_copies.push_back(*aggregate_ptrs[i]); + } + auto ac = AggregateCombo::Create(std::move(agg_copies)); + result->Reset(new AggregateCombo(std::move(ac))); + }); +} + +void deephaven_client_AggregateCombo_dtor(NativePtr self) { + delete self.Get(); +} + +void deephaven_client_Aggregate_dtor(NativePtr self) { + delete self.Get(); +} + +void deephaven_client_Aggregate_AbsSum( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::AbsSum(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Group( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Group(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Avg( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Avg(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Count( + const char *column, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + result->Reset(new Aggregate(Aggregate::Count(column))); + }); +} + +void deephaven_client_Aggregate_First( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::First(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Last( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Last(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Max( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Max(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Med( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Med(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Min( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Min(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Pct( + double percentile, InteropBool avg_median, + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Pct(percentile, (bool)avg_median, std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Std( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Std(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Sum( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Sum(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_Var( + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::Var(std::move(cols)))); + }); +} + +void deephaven_client_Aggregate_WAvg(const char *weight, + const char **columns, int32_t num_columns, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + auto cols = std::vector(columns, columns + num_columns); + result->Reset(new Aggregate(Aggregate::WAvg(std::string(weight), std::move(cols)))); + }); +} + +void deephaven_client_utility_DurationSpecifier_ctor_nanos(int64_t nanos, + NativePtr *result, + ErrorStatus *status) { + status->Run([=] { + result->Reset(new DurationSpecifier(nanos)); + }); +} + +void deephaven_client_utility_DurationSpecifier_ctor_durationstr( + const char *duration_str, + NativePtr *result, + ErrorStatus *status) { + status->Run([=] { + result->Reset(new DurationSpecifier(duration_str)); + }); +} + +void deephaven_client_utility_DurationSpecifier_dtor(NativePtr self) { + delete self.Get(); +} + +void deephaven_client_utility_TimePointSpecifier_ctor_nanos( + int64_t nanos, + NativePtr *result, + ErrorStatus *status) { + status->Run([=] { + result->Reset(new TimePointSpecifier(nanos)); + }); +} + +void deephaven_client_utility_TimePointSpecifier_ctor_timepointstr( + const char *time_point_str, + NativePtr *result, + ErrorStatus *status) { + status->Run([=] { + result->Reset(new TimePointSpecifier(time_point_str)); + }); +} + +void deephaven_client_utility_TimePointSpecifier_dtor(NativePtr self) { + delete self.Get(); +} + +void deephaven_dhclient_utility_TableMaker_ctor( + NativePtr *result, + ErrorStatus *status) { + status->Run([=] { + result->Reset(new TableMaker()); + }); +} + +void deephaven_dhclient_utility_TableMaker_dtor(NativePtr self) { + delete self.Get(); +} + +void deephaven_dhclient_utility_TableMaker_MakeTable( + NativePtr self, + NativePtr manager, + NativePtr *result, + ErrorStatus *status) { + status->Run([=] { + auto th = self->MakeTable(*manager); + result->Reset(new TableHandle(std::move(th))); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__CharAsInt16( + NativePtr self, + const char *name, const int16_t *data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) -> int16_t { return static_cast(data[index]); }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__Int8( + NativePtr self, + const char *name, const int8_t *data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) { return data[index]; }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__Int16( + NativePtr self, + const char *name, const int16_t *data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) { return data[index]; }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__Int32( + NativePtr self, + const char *name, const int32_t *data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) { return data[index]; }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__Int64( + NativePtr self, + const char *name, const int64_t *data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) { return data[index]; }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__Float( + NativePtr self, + const char *name, const float *data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) { return data[index]; }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__Double( + NativePtr self, + const char *name, const double *data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) { return data[index]; }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__BoolAsInteropBool( + NativePtr self, + const char *name, const int8_t *data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) { return data[index] != 0; }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__DateTimeAsInt64( + NativePtr self, + const char *name, const int64_t *data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) { return DateTime::FromNanos(data[index]); }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} + +void deephaven_dhclient_utility_TableMaker_AddColumn__String( + NativePtr self, + const char *name, const char **data, int32_t length, + const InteropBool *optional_nulls, + ErrorStatus *status) { + status->Run([=] { + auto get_value = [=](size_t index) -> std::string { + if (data[index] == nullptr) { + return ""; + } + return data[index]; + }; + auto is_null = [=](size_t index) { return optional_nulls != nullptr && (bool)optional_nulls[index]; }; + self->AddColumn(name, get_value, is_null, length); + }); +} +} // extern "C" diff --git a/cpp-client/deephaven/dhclient/src/interop/client_options_interop.cc b/cpp-client/deephaven/dhclient/src/interop/client_options_interop.cc new file mode 100644 index 00000000000..3a40e861d12 --- /dev/null +++ b/cpp-client/deephaven/dhclient/src/interop/client_options_interop.cc @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#include "deephaven/client/interop/client_options_interop.h" + +#include "deephaven/client/client.h" +#include "deephaven/client/client_options.h" +#include "deephaven/dhcore/interop/interop_util.h" + +using deephaven::dhcore::interop::ErrorStatus; +using deephaven::dhcore::interop::InteropBool; +using deephaven::dhcore::interop::NativePtr; + +using deephaven::client::ClientOptions; + +extern "C" { +void deephaven_client_ClientOptions_ctor(NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + result->Reset(new ClientOptions()); + }); +} + +void deephaven_client_ClientOptions_dtor(NativePtr self) { + delete self; +} + +void deephaven_client_ClientOptions_SetDefaultAuthentication(NativePtr self, + ErrorStatus *status) { + status->Run([=]() { + self->SetDefaultAuthentication(); + }); +} + +void deephaven_client_ClientOptions_SetBasicAuthentication(NativePtr self, + const char *username, const char *password, + ErrorStatus *status) { + status->Run([=]() { + self->SetBasicAuthentication(username, password); + }); +} + +void deephaven_client_ClientOptions_SetCustomAuthentication(NativePtr self, + const char *authentication_key, const char *authentication_value, + ErrorStatus *status) { + status->Run([=]() { + self->SetCustomAuthentication(authentication_key, authentication_value); + }); +} + +void deephaven_client_ClientOptions_SetSessionType(NativePtr self, + const char *session_type, + ErrorStatus *status) { + status->Run([=]() { + self->SetSessionType(session_type); + }); +} + +void deephaven_client_ClientOptions_SetUseTls(NativePtr self, + InteropBool use_tls, + ErrorStatus *status) { + status->Run([=]() { + self->SetUseTls((bool)use_tls); + }); + +} + +void deephaven_client_ClientOptions_SetTlsRootCerts(NativePtr self, + const char *tls_root_certs, + ErrorStatus *status) { + status->Run([=]() { + self->SetTlsRootCerts(tls_root_certs); + }); +} + +void deephaven_client_ClientOptions_SetClientCertChain(NativePtr self, + const char *client_cert_chain, + ErrorStatus *status) { + status->Run([=]() { + self->SetClientCertChain(client_cert_chain); + }); + +} + +void deephaven_client_ClientOptions_SetClientPrivateKey(NativePtr self, + const char *client_private_key, + ErrorStatus *status) { + status->Run([=]() { + self->SetClientPrivateKey(client_private_key); + }); + +} + +void deephaven_client_ClientOptions_AddIntOption(NativePtr self, + const char *opt, int32_t val, + ErrorStatus *status) { + status->Run([=]() { + self->AddIntOption(opt, val); + }); + +} + +void deephaven_client_ClientOptions_AddStringOption(NativePtr self, + const char *opt, const char *val, + ErrorStatus *status) { + status->Run([=]() { + self->AddStringOption(opt, val); + }); +} + +void deephaven_client_ClientOptions_AddExtraHeader(NativePtr self, + const char *header_name, const char *header_value, + ErrorStatus *status) { + status->Run([=]() { + self->AddExtraHeader(header_name, header_value); + }); +} +} // extern "C" diff --git a/cpp-client/deephaven/dhclient/src/interop/update_by_interop.cc b/cpp-client/deephaven/dhclient/src/interop/update_by_interop.cc new file mode 100644 index 00000000000..49c5c56ab0f --- /dev/null +++ b/cpp-client/deephaven/dhclient/src/interop/update_by_interop.cc @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#include "deephaven/client/interop/update_by_interop.h" + +#include "deephaven/client/client.h" +#include "deephaven/client/client_options.h" +#include "deephaven/client/update_by.h" +#include "deephaven/dhcore/interop/interop_util.h" + +using deephaven::dhcore::interop::ErrorStatus; +using deephaven::dhcore::interop::InteropBool; +using deephaven::dhcore::interop::NativePtr; + +using deephaven::client::ClientOptions; +using deephaven::client::UpdateByOperation; +using deephaven::client::update_by::DeltaControl; +using deephaven::client::update_by::OperationControl; +using deephaven::client::utility::DurationSpecifier; + +namespace { +void WithColsHelper(const char **cols, int32_t num_cols, + NativePtr *result, + ErrorStatus *status, + UpdateByOperation (*fp)(std::vector)) { + status->Run([=]() { + std::vector columns(cols, cols + num_cols); + auto ubo = (*fp)(std::move(columns)); + result->Reset(new UpdateByOperation(std::move(ubo))); + }); +} + +void WithTicksHelper(double decay_ticks, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status, + UpdateByOperation (*fp)(double, std::vector, const OperationControl &)) { + status->Run([=]() { + std::vector columns(cols, cols + num_cols); + auto ubo = (*fp)(decay_ticks, std::move(columns), *op_control); + result->Reset(new UpdateByOperation(std::move(ubo))); + }); +} + +void WithTimeHelper(const char *timestamp_col, + NativePtr decay_time, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status, + UpdateByOperation (*fp)(std::string, DurationSpecifier, std::vector, const OperationControl &)) { + status->Run([=]() { + std::vector columns(cols, cols + num_cols); + auto ubo = (*fp)(timestamp_col, *decay_time, std::move(columns), *op_control); + result->Reset(new UpdateByOperation(std::move(ubo))); + }); +} + +void WithRollingTicksHelper( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status, + UpdateByOperation (*fp)(std::vector, int32_t, int32_t)) { + status->Run([=]() { + std::vector columns(cols, cols + num_cols); + auto ubo = (*fp)(std::move(columns), rev_ticks, fwd_ticks); + result->Reset(new UpdateByOperation(std::move(ubo))); + }); +} + +void WithRollingTimeHelper(const char *timestamp_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status, + UpdateByOperation (*fp)(std::string, std::vector, DurationSpecifier, DurationSpecifier)) { + status->Run([=]() { + std::vector columns(cols, cols + num_cols); + auto ubo = (*fp)(timestamp_col, std::move(columns), *rev_time, *fwd_time); + result->Reset(new UpdateByOperation(std::move(ubo))); + }); +} + +void WithRollingWavgTicksHelper(const char *weight_col, + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status, + UpdateByOperation (*fp)(std::string, std::vector, int32_t, int32_t)) { + status->Run([=]() { + std::vector columns(cols, cols + num_cols); + auto ubo = (*fp)(weight_col, std::move(columns), rev_ticks, fwd_ticks); + result->Reset(new UpdateByOperation(std::move(ubo))); + }); +} + +void WithRollingWavgTimeHelper(const char *timestamp_col, const char *weight_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status, + UpdateByOperation (*fp)(std::string, std::string, std::vector, DurationSpecifier, DurationSpecifier)) { + status->Run([=]() { + std::vector columns(cols, cols + num_cols); + auto ubo = (*fp)(timestamp_col, weight_col, std::move(columns), *rev_time, *fwd_time); + result->Reset(new UpdateByOperation(std::move(ubo))); + }); +} +} // namespace + +extern "C" { +void deephaven_client_UpdateByOperation_dtor( + NativePtr self) { + delete self.Get(); +} + +void deephaven_client_update_by_cumSum( + const char **cols, int32_t num_cols, + NativePtr *result, + ErrorStatus *status) { + WithColsHelper(cols, num_cols, result, status, &deephaven::client::update_by::cumSum); +} + +void deephaven_client_update_by_cumProd( + const char **cols, int32_t num_cols, + NativePtr *result, + ErrorStatus *status) { + WithColsHelper(cols, num_cols, result, status, &deephaven::client::update_by::cumProd); +} + +void deephaven_client_update_by_cumMin( + const char **cols, int32_t num_cols, + NativePtr *result, + ErrorStatus *status) { + WithColsHelper(cols, num_cols, result, status, &deephaven::client::update_by::cumMin); +} + +void deephaven_client_update_by_cumMax( + const char **cols, int32_t num_cols, + NativePtr *result, + ErrorStatus *status) { + WithColsHelper(cols, num_cols, result, status, &deephaven::client::update_by::cumMax); +} + +void deephaven_client_update_by_forwardFill( + const char **cols, int32_t num_cols, + NativePtr *result, + ErrorStatus *status) { + WithColsHelper(cols, num_cols, result, status, &deephaven::client::update_by::forwardFill); +} + +void deephaven_client_update_by_delta( + const char **cols, int32_t num_cols, + deephaven::client::update_by::DeltaControl delta_control, + NativePtr *result, + ErrorStatus *status) { + status->Run([=]() { + std::vector columns(cols, cols + num_cols); + auto ubo = deephaven::client::update_by::delta(std::move(columns), delta_control); + result->Reset(new UpdateByOperation(std::move(ubo))); + }); +} + +void deephaven_client_update_by_emaTick(double decay_ticks, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTicksHelper(decay_ticks, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emaTick); +} + +void deephaven_client_update_by_emaTime(const char *timestamp_col, + NativePtr decay_time, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTimeHelper(timestamp_col, decay_time, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emaTime); +} + +void deephaven_client_update_by_emsTick(double decay_ticks, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTicksHelper(decay_ticks, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emsTick); +} + +void deephaven_client_update_by_emsTime(const char *timestamp_col, + deephaven::dhcore::interop::NativePtr decay_time, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTimeHelper(timestamp_col, decay_time, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emsTime); +} + +void deephaven_client_update_by_emminTick(double decay_ticks, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTicksHelper(decay_ticks, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emminTick); +} + +void deephaven_client_update_by_emminTime(const char *timestamp_col, + deephaven::dhcore::interop::NativePtr decay_time, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTimeHelper(timestamp_col, decay_time, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emminTime); +} + +void deephaven_client_update_by_emmaxTick(double decay_ticks, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTicksHelper(decay_ticks, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emmaxTick); +} + +void deephaven_client_update_by_emmaxTime(const char *timestamp_col, + deephaven::dhcore::interop::NativePtr decay_time, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTimeHelper(timestamp_col, decay_time, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emmaxTime); +} + +void deephaven_client_update_by_emstdTick(double decay_ticks, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTicksHelper(decay_ticks, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emstdTick); +} + +void deephaven_client_update_by_emstdTime(const char *timestamp_col, + deephaven::dhcore::interop::NativePtr decay_time, + const char **cols, int32_t num_cols, + const OperationControl *op_control, + NativePtr *result, + ErrorStatus *status) { + WithTimeHelper(timestamp_col, decay_time, cols, num_cols, op_control, result, status, + &deephaven::client::update_by::emstdTime); +} + +void deephaven_client_update_by_rollingSumTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status) { + WithRollingTicksHelper(cols, num_cols, rev_ticks, fwd_ticks, result, status, + &deephaven::client::update_by::rollingSumTick); +} + +void deephaven_client_update_by_rollingSumTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status) { + WithRollingTimeHelper(timestamp_col, cols, num_cols, rev_time, fwd_time, result, status, + &deephaven::client::update_by::rollingSumTime); +} + +void deephaven_client_update_by_rollingGroupTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status) { + WithRollingTicksHelper(cols, num_cols, rev_ticks, fwd_ticks, result, status, + &deephaven::client::update_by::rollingGroupTick); +} + +void deephaven_client_update_by_rollingGroupTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status) { + WithRollingTimeHelper(timestamp_col, cols, num_cols, rev_time, fwd_time, result, status, + &deephaven::client::update_by::rollingGroupTime); +} + +void deephaven_client_update_by_rollingAvgTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status) { + WithRollingTicksHelper(cols, num_cols, rev_ticks, fwd_ticks, result, status, + &deephaven::client::update_by::rollingAvgTick); +} + +void deephaven_client_update_by_rollingAvgTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status) { + WithRollingTimeHelper(timestamp_col, cols, num_cols, rev_time, fwd_time, result, status, + &deephaven::client::update_by::rollingAvgTime); +} + +void deephaven_client_update_by_rollingMinTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status) { + WithRollingTicksHelper(cols, num_cols, rev_ticks, fwd_ticks, result, status, + &deephaven::client::update_by::rollingMinTick); +} + +void deephaven_client_update_by_rollingMinTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status) { + WithRollingTimeHelper(timestamp_col, cols, num_cols, rev_time, fwd_time, result, status, + &deephaven::client::update_by::rollingMinTime); +} + +void deephaven_client_update_by_rollingMaxTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status) { + WithRollingTicksHelper(cols, num_cols, rev_ticks, fwd_ticks, result, status, + &deephaven::client::update_by::rollingMaxTick); +} + +void deephaven_client_update_by_rollingMaxTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status) { + WithRollingTimeHelper(timestamp_col, cols, num_cols, rev_time, fwd_time, result, status, + &deephaven::client::update_by::rollingMaxTime); +} + +void deephaven_client_update_by_rollingProdTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status) { + WithRollingTicksHelper(cols, num_cols, rev_ticks, fwd_ticks, result, status, + &deephaven::client::update_by::rollingProdTick); +} + +void deephaven_client_update_by_rollingProdTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status) { + WithRollingTimeHelper(timestamp_col, cols, num_cols, rev_time, fwd_time, result, status, + &deephaven::client::update_by::rollingProdTime); +} + +void deephaven_client_update_by_rollingCountTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status) { + WithRollingTicksHelper(cols, num_cols, rev_ticks, fwd_ticks, result, status, + &deephaven::client::update_by::rollingCountTick); +} + +void deephaven_client_update_by_rollingCountTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status) { + WithRollingTimeHelper(timestamp_col, cols, num_cols, rev_time, fwd_time, result, status, + &deephaven::client::update_by::rollingCountTime); +} + +void deephaven_client_update_by_rollingStdTick( + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status) { + WithRollingTicksHelper(cols, num_cols, rev_ticks, fwd_ticks, result, status, + &deephaven::client::update_by::rollingStdTick); +} + +void deephaven_client_update_by_rollingStdTime(const char *timestamp_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status) { + WithRollingTimeHelper(timestamp_col, cols, num_cols, rev_time, fwd_time, result, status, + &deephaven::client::update_by::rollingStdTime); +} + +void deephaven_client_update_by_rollingWavgTick(const char *weight_col, + const char **cols, int32_t num_cols, + int32_t rev_ticks, int32_t fwd_ticks, + NativePtr *result, + ErrorStatus *status) { + WithRollingWavgTicksHelper(weight_col, cols, num_cols, rev_ticks, fwd_ticks, result, status, + &deephaven::client::update_by::rollingWavgTick); +} + +void deephaven_client_update_by_rollingWavgTime(const char *timestamp_col, + const char *weight_col, + const char **cols, int32_t num_cols, + NativePtr rev_time, + NativePtr fwd_time, + NativePtr *result, + ErrorStatus *status) { + WithRollingWavgTimeHelper(timestamp_col, weight_col, cols, num_cols, rev_time, fwd_time, + result, status, + &deephaven::client::update_by::rollingWavgTime); +} +} // extern "C" diff --git a/cpp-client/deephaven/dhcore/CMakeLists.txt b/cpp-client/deephaven/dhcore/CMakeLists.txt index 90a850253a8..4209f7cc974 100644 --- a/cpp-client/deephaven/dhcore/CMakeLists.txt +++ b/cpp-client/deephaven/dhcore/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 17) # for CMAKE_INSTALL_{dir} include(GNUInstallDirs) -find_package(Immer REQUIRED) +find_package(Immer CONFIG REQUIRED) set(ALL_FILES src/types.cc @@ -21,6 +21,8 @@ set(ALL_FILES src/container/row_sequence.cc src/immerutil/abstract_flex_vector.cc src/immerutil/immer_column_source.cc + src/interop/testapi/basic_interop_interactions.cc + src/interop/interop_util.cc src/ticking/barrage_processor.cc src/ticking/immer_table_state.cc src/ticking/index_decoder.cc @@ -47,6 +49,8 @@ set(ALL_FILES include/public/deephaven/dhcore/column/column_source_helpers.h include/public/deephaven/dhcore/column/column_source_utils.h include/public/deephaven/dhcore/container/row_sequence.h + include/public/deephaven/dhcore/interop/testapi/basic_interop_interactions.h + include/public/deephaven/dhcore/interop/interop_util.h include/public/deephaven/dhcore/ticking/barrage_processor.h include/public/deephaven/dhcore/ticking/ticking.h include/public/deephaven/dhcore/utility/cython_support.h @@ -138,5 +142,5 @@ foreach (whichlib dhcore dhcore_static) target_include_directories(${whichlib} PRIVATE flatbuf) target_include_directories(${whichlib} PUBLIC $) - target_link_libraries(${whichlib} PUBLIC immer) + target_link_libraries(${whichlib} PRIVATE immer) endforeach() diff --git a/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/clienttable/schema.h b/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/clienttable/schema.h index fca7665bcbb..bc0630a097a 100644 --- a/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/clienttable/schema.h +++ b/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/clienttable/schema.h @@ -38,7 +38,7 @@ class Schema { ~Schema(); [[nodiscard]] - std::optional GetColumnIndex(std::string_view name, bool strict) const; + std::optional GetColumnIndex(std::string_view name, bool strict) const; [[nodiscard]] const std::vector &Names() const { @@ -51,8 +51,8 @@ class Schema { } [[nodiscard]] - size_t NumCols() const { - return names_.size(); + int32_t NumCols() const { + return static_cast(names_.size()); } private: diff --git a/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/interop/interop_util.h b/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/interop/interop_util.h new file mode 100644 index 00000000000..19b9cc2fc65 --- /dev/null +++ b/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/interop/interop_util.h @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#pragma once +#include +#include +#include +#include +#include +#include +#include + +namespace deephaven::dhcore::interop { +/** + * This class simply wraps a pointer. It is meant to mirror a similar struct on the C# side, namely + * + * [StructLayout(LayoutKind.Sequential)] + * public struct NativePtr { + * public IntPtr ptr; + * } + * + * The purpose of all of this is to enable a little more type checking on the C# side. + * Rather than just dealing with IntPtr on the C# side (which is effectively equivalent to + * (void*) and has just as little typechecking, we use NativePtr struct instead. + * This prevents us from making mistakes like passing a NativePtr when we meant + * NativePtr. Our protocol is that .NET passes us a NativePtr by value, so + * in our C API, we receive a NativePtr by value. + * + * There is a little cheat we use because the pointers aren't fully typechecked. + * + * On the C++ side, we will have a NativePtr which points to a deephaven::client::Client + * object. The C# side doesn't have access to the *actual* deephaven::client::Client, nor would + * we want it to. Instead, on the .NET side we have a static "proxy" class called "NativeClient" which + * has no instance or data members. It happens to be where we keep our (static) interop method + * definitions but it has no other function. + * + * In summary on the C++ side, we will have a Client*, which we will then wrap as NativePtr + * and return to C#. C# will get this as NativePtr. This is fine because it's an + * opaque pointer. The C# code can't do anything with it except pass it back to C++ at some future + * point, where it will be interpreted again as a NativePtr, and the internal Client* can + * be pulled back out of it. + */ +template +struct NativePtr { + explicit NativePtr(T *ptr) : ptr_(ptr) {} + + [[nodiscard]] + T *Get() const { return ptr_; } + + [[nodiscard]] + operator T*() const { return ptr_; } + + [[nodiscard]] + T *operator ->() const { return ptr_; } + + void Reset(T *new_ptr) { ptr_ = new_ptr; } + +private: + T *ptr_ = nullptr; +}; + +/** + * It is not safe to pass .NET bool over interop. Instead we pass a struct which wraps + * an int8_t. On the C++ side we have an explicit constructor and an explicit conversion + * operator, to make it a bit more pleasant to convert to/from. + */ +class InteropBool { +public: + explicit InteropBool(bool value) : value_(value ? 1 : 0) {} + + explicit operator bool() const { return value_ != 0; } + +private: + int8_t value_ = 0; +}; + +/** + * The following classes support our protocol for getting strings back from C++ to .NET. + * Here is some background: + * + * Getting strings in the forward direction (.NET to C++) is easy: we can just take a + * const char *. This is a UTF-8 formatted string, terminated by NUL, whose memory is owned + * by .NET. (So we can look at the strings or copy them, but we can't hold on to the pointer). + * + * Getting strings in the reverse direction (C++ to .NET) takes a little more effort. + * The technique we use is to pack the (UTF-8) string data to be returned into a "StringPool", + * and then the .NET caller makes a second call to copy over the string data. + * + * The following data structures participate in this protocol: + * StringPoolBuilder - helper class used on the C++ side to build a StringPool + * StringPool - the StringPool (still on the C++ side) that holds final set of packed strings + * StringHandle - Opaque "handle" to a string in the StringPool (implementation: a zero-based index). + * This is passed back to the .NET side. + * StringPoolHandle - A "handle" to the StringPool. Contains a pointer to the StringPool on the C++ + * side, plus the total number of bytes in the packed strings, plus the number of strings + * in the pool. This is passed back to the .NET side. Given this information, the .NET side will + * allocate buffers and then call back into C++ side to populate those buffers. + * + * Rough example from C# side: + * void Doit() { + * InvokeSomeCPlusPlusMethod(args, out StringHandle stringHandle0, + * out StringHandle stringHandle1, out StringPoolHandle stringPoolHandle); + * var packedText = new byte[stringPoolHandle.numBytes_]; + * var stringEnds = new Int32[stringPoolHandle.numStrings_]; + * // This is an interop call that does three things: + * // it copies the "packedText" data into the array we just allocated on the C# side + * // it copies the "stringEnds" data into the array we just allocated on the C# side + * // Then it calls "delete" on the stringPoolHandle.stringPool_ pointer (so we can only + * // call this entry point once). + * var errorCode = deephaven_dhcore_interop_StringPool_ExportAndDestroy( + * stringPoolHandle.stringPool_, + * packedText, packedText.Length, + * stringEnds, stringEnds.Length); + * + * // Now we have our string data: + * // The first byte of string[0] is at offset 0. The (exclusive) end byte is at stringEnds[0]. + * // The first byte of string[1] is at stringEnds[0]. The (exclusive) end byte is stringEnds[1]. + * // ... + * // The first byte of string[N] is at stringEnds[N-1]. The (exclusive) end byte is stringEnds[N]. + * + * // The individual strings that the method wanted to return are referred to by index + * // as "StringHandles". Their start and end text position is calculated by looking inside + * // stringEnds_ + * + * var string0Begin = stringHandle0.index_ == 0 ? 0 : stringEnds[stringHandle0.index_ - 1]; + * var string0End = stringEnds[stringHandle0.index_]; + * + * var string1Begin = stringHandle1.index_ ==0 ? 0 : stringEnds[stringHandle1.index_ - 1]; + * var string1End = stringEnds[stringHandle1.index_]; + * + * var string0 = Encoding.UTF8.GetString(packedText, string0Begin, string0End - string0Begin); + * var string1 = Encoding.UTF8.GetString(packedText, string1Begin, string1End - string1Begin); + * + * deephaven_dhcore_interop_StringPool_ExportAndDestroy should not fail, unless you call it + * with bad arguments. For completeness it returns an error code: 0 for success and nonzero for + * error. Getting a nonzero value should be considered a catastrophic programming error. + * + * In C# we have a class StringPoolHandle that implements the above interaction for us. + * It has the same data layout as the C++ class, but it has a method called ExportAndDestroy + * that does the above interaction and returns a C# StringPool. The C# StringPool does not + * have much to do with the C++ class of the same name, except that they both conceptually + * represent a pool of strings. On C#, it is very simple and contains an array of the digested + * strings: + * + * public sealed class StringPool { + * public readonly string[] Strings; + * public StringPool(string[] strings) => Strings = strings; + * public string Get(StringHandle handle) { + * return Strings[handle.Index]; + * } + * } + * + * On the C++ side, it contains the packed text and the string end positions. + */ + +class StringPool { +public: + static int32_t ExportAndDestroy( + StringPool *self, + uint8_t *bytes, int32_t bytes_length, + int32_t *ends, int32_t ends_length); + + StringPool(std::vector bytes, std::vector ends); + StringPool(const StringPool &other) = delete; + StringPool &operator=(const StringPool &other) = delete; + ~StringPool(); + +private: + std::vector bytes_; + std::vector ends_; +}; + +struct StringHandle { + explicit StringHandle(int32_t index) : index_(index) {} + + int32_t index_ = 0; +}; + +struct StringPoolHandle { + StringPoolHandle() = default; + StringPoolHandle(StringPool *string_pool, int32_t num_bytes, int32_t num_strings) : + stringPool_(string_pool), numBytes_(num_bytes), numStrings_(num_strings) {} + + StringPool *stringPool_ = nullptr; + int32_t numBytes_ = 0; + int32_t numStrings_ = 0; +}; + +class StringPoolBuilder { +public: + StringPoolBuilder(); + StringPoolBuilder(const StringPoolBuilder &other) = delete; + StringPoolBuilder &operator=(const StringPoolBuilder &other) = delete; + ~StringPoolBuilder(); + + [[nodiscard]] + StringHandle Add(std::string_view sv); + [[nodiscard]] + StringPoolHandle Build(); + +private: + std::vector bytes_; + std::vector ends_; +}; + +/** + * ErrorStatus is our "out" struct that returns error information to the caller. We represent + * error returns as strings (basically the stringified version of the C++ exception that was + * thrown). + * + * The ErrorStatus representation is fairly simple: just a handle to a string pool and a + * handle to a string. On success the StringPoolHandle will point to an empty StringPool. + * On failure, the StringPoolHandle will point to a StringPool containing one string, and the + * StringHandle will be a handle to that string. Careful readers will note that if there is + * an error, the StringHandle will always point to the first string, and therefore always + * have index 0. If we cared about saving a few bytes, we could eliminate this field, but + * there is no need to care about saving a few bytes at this point. + */ +class ErrorStatus { +public: + /** + * This is a convenience method used by C++ code to wrap a lambda and catch exceptions. + * If the lambda completes, then the StringPoolBuilder will be empty. If the lambda + * fails with an exception, the exception text is stored in the StringPoolBuilder and + * the StringHandle is set. In either case the (empty or populated) StringPool is built. + */ + template + void Run(const T &callback) { + StringPoolBuilder builder; + try { + // Sanity check for this method's callers to make sure they're not returning a value + // which would be a programming mistake because it is ignored here. + static_assert(std::is_same_v); + callback(); + } catch (const std::exception &e) { + stringHandle_ = builder.Add(e.what()); + } catch (...) { + stringHandle_ = builder.Add("Unknown exception"); + } + stringPoolHandle_ = builder.Build(); + } + +private: + StringHandle stringHandle_; + StringPoolHandle stringPoolHandle_; +}; +} // namespace deephaven::dhcore::interop + +extern "C" { +int32_t deephaven_dhcore_interop_StringPool_ExportAndDestroy( + deephaven::dhcore::interop::NativePtr string_pool, + uint8_t *bytes, int32_t bytes_length, + int32_t *ends, int32_t ends_length); +} // extern "C" diff --git a/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/interop/testapi/basic_interop_interactions.h b/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/interop/testapi/basic_interop_interactions.h new file mode 100644 index 00000000000..be4585f7a54 --- /dev/null +++ b/cpp-client/deephaven/dhcore/include/public/deephaven/dhcore/interop/testapi/basic_interop_interactions.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#pragma once + +#include +#include "deephaven/dhcore/interop/interop_util.h" + +namespace deephaven::dhcore::interop::testapi { +/** + * A simple struct that we use to confirm we can pass between C++ and C#. + */ +struct BasicStruct { + BasicStruct(int32_t i, double d) : i_(i), d_(d) {} + + [[nodiscard]] + BasicStruct Add(const BasicStruct &other) const { + return BasicStruct(i_ + other.i_, d_ + other.d_); + } + + int32_t i_; + double d_; +}; + +/** + * A nested struct that we use to confirm we can pass between C++ and C#. + */ +struct NestedStruct { + NestedStruct(const BasicStruct &a, const BasicStruct &b) : a_(a), b_(b) {} + + [[nodiscard]] + NestedStruct Add(const NestedStruct &other) const { + return NestedStruct(a_.Add(other.a_), b_.Add(other.b_)); + } + + BasicStruct a_; + BasicStruct b_; +}; +} + +extern "C" { +/** + * Adds 'a' and 'b', stores a result in *result. + * Tests passing int32 back and forth. + * Note: although interop supports returning a value, we typically always + * return void and use "out" parameters for everything. We do this for simplicity + * and consistency: our style is to have zero or more 'out' parameters of simple types + * and typically one more 'out' parameter for the ErrorStatus struct which contains + * our exception/error information. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_Add( + int32_t a, int32_t b, int32_t *result); + +/** + * Adds the arrays 'a' and 'b' elementwise, stores the results in *result. The caller + * needs to allocate an array of 'length' elements for 'result'. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddArrays( + const int32_t *a, const int32_t *b, int32_t length, int32_t *result); + +/** + * Performs a XOR b, stores result in *result. Demonstrates our use of InteropBool, + * because regular C# bool doesn't interop with C++ bool. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_Xor( + deephaven::dhcore::interop::InteropBool a, + deephaven::dhcore::interop::InteropBool b, + deephaven::dhcore::interop::InteropBool *result); + +/** + * Performs an elementwise XOR of the a and b arrays, stores result in *result. + * The caller needs to allocate an array of 'length' elements for 'result'. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_XorArrays( + const deephaven::dhcore::interop::InteropBool *a, + const deephaven::dhcore::interop::InteropBool *b, + int32_t length, + deephaven::dhcore::interop::InteropBool *result); + +/** + * Concats strings a and b, stores the result in string_pool_handle and result_handle. + * Demonstrates our StringPool protocol. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_Concat( + const char *a, const char *b, + deephaven::dhcore::interop::StringHandle *result_handle, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle); + +/** + * Concats arrays of strings a and b, elementwise, and stores the results in + * string_pool_handle and result_handles. The caller needs to allocate an array + * of 'length' elements for 'result_handles'. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_ConcatArrays(const char **a, + const char **b, int32_t length, + deephaven::dhcore::interop::StringHandle *result_handles, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle); + +/** + * Adds the structs a and b, fieldwise, and stores the result in *result. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddBasicStruct( + const deephaven::dhcore::interop::testapi::BasicStruct *a, + const deephaven::dhcore::interop::testapi::BasicStruct *b, + deephaven::dhcore::interop::testapi::BasicStruct *result); + +/** + * Adds arrays of the structs a and b, elementwise, and then fieldwise, and stores the result in + * *result. The caller needs to allocate an array of 'length' elements for 'result'. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddBasicStructArrays( + const deephaven::dhcore::interop::testapi::BasicStruct *a, + const deephaven::dhcore::interop::testapi::BasicStruct *b, + int32_t length, + deephaven::dhcore::interop::testapi::BasicStruct *result); + +/** + * Adds the structs a and b, fieldwise, and stores the result in *result. + * a and b are "nested structs" containing other structs. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddNestedStruct( + const deephaven::dhcore::interop::testapi::NestedStruct *a, + const deephaven::dhcore::interop::testapi::NestedStruct *b, + deephaven::dhcore::interop::testapi::NestedStruct *result); + +/** + * Adds arrays of the structs a and b, elementwise, and then fieldwise, and stores the result in + * *result. * a and b are "nested structs" containing other structs. The caller needs to + * allocate an array of 'length' elements for 'result'. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddNestedStructArrays( + const deephaven::dhcore::interop::testapi::NestedStruct *a, + const deephaven::dhcore::interop::testapi::NestedStruct *b, + int32_t length, + deephaven::dhcore::interop::testapi::NestedStruct *result); + +/** + * Tests our error protocol. Sets an error if a < b. + */ +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_SetErrorIfLessThan( + int32_t a, int32_t b, + deephaven::dhcore::interop::ErrorStatus *error_status); +} // extern "C" diff --git a/cpp-client/deephaven/dhcore/src/clienttable/schema.cc b/cpp-client/deephaven/dhcore/src/clienttable/schema.cc index f50660fc967..31ab8c95178 100644 --- a/cpp-client/deephaven/dhcore/src/clienttable/schema.cc +++ b/cpp-client/deephaven/dhcore/src/clienttable/schema.cc @@ -28,10 +28,10 @@ Schema::Schema(Private, std::vector names, std::vector Schema::GetColumnIndex(std::string_view name, bool strict) const { +std::optional Schema::GetColumnIndex(std::string_view name, bool strict) const { auto ip = index_.find(name); if (ip != index_.end()) { - return ip->second; + return static_cast(ip->second); } // Not found: check strictness flag. if (!strict) { diff --git a/cpp-client/deephaven/dhcore/src/interop/interop_util.cc b/cpp-client/deephaven/dhcore/src/interop/interop_util.cc new file mode 100644 index 00000000000..520a24c177f --- /dev/null +++ b/cpp-client/deephaven/dhcore/src/interop/interop_util.cc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#include "deephaven/dhcore/interop/interop_util.h" +#include "deephaven/dhcore/utility/utility.h" + +#include + +using deephaven::dhcore::interop::NativePtr; +using deephaven::dhcore::interop::StringPool; +using deephaven::dhcore::utility::MakeReservedVector; + +namespace deephaven::dhcore::interop { +int32_t StringPool::ExportAndDestroy(StringPool *self, + uint8_t *bytes, int32_t bytes_length, + int32_t *ends, int32_t ends_length) { + // StringPoolBuilder::Build is allowed to return null if there are no strings. + if (self == nullptr) { + if (bytes_length != 0 || ends_length != 0) { + // This arbitrary return code indicates that something has gone wrong. + return 1; + } + return 0; + } + if (bytes_length != static_cast(self->bytes_.size()) || + ends_length != static_cast(self->ends_.size())) { + // This arbitrary return code indicates that something has gone wrong. + return 2; + } + std::copy(self->bytes_.begin(), self->bytes_.end(), bytes); + std::copy(self->ends_.begin(), self->ends_.end(), ends); + delete self; + return 0; +} + +StringPool::StringPool(std::vector bytes, std::vector ends) : + bytes_(std::move(bytes)), ends_(std::move(ends)) {} +StringPool::~StringPool() = default; + +StringPoolBuilder::StringPoolBuilder() = default; +StringPoolBuilder::~StringPoolBuilder() = default; + +StringHandle StringPoolBuilder::Add(std::string_view sv) { + StringHandle result(static_cast(ends_.size())); + bytes_.insert(bytes_.end(), sv.begin(), sv.end()); + ends_.push_back(static_cast(bytes_.size())); + return result; +} + +StringPoolHandle StringPoolBuilder::Build() { + auto num_bytes = bytes_.size(); + auto num_strings = ends_.size(); + if (num_strings == 0) { + return StringPoolHandle(nullptr, 0, 0); + } + auto *sp = new StringPool(std::move(bytes_), std::move(ends_)); + return StringPoolHandle(sp, static_cast(num_bytes), + static_cast(num_strings)); +} +} // namespace deephaven::dhcore::interop + +extern "C" { +int32_t deephaven_dhcore_interop_StringPool_ExportAndDestroy( + NativePtr string_pool, + uint8_t *bytes, int32_t bytes_length, + int32_t *ends, int32_t ends_length) { + return StringPool::ExportAndDestroy(string_pool.Get(), bytes, bytes_length, ends, ends_length); +} +} // extern "C" diff --git a/cpp-client/deephaven/dhcore/src/interop/testapi/basic_interop_interactions.cc b/cpp-client/deephaven/dhcore/src/interop/testapi/basic_interop_interactions.cc new file mode 100644 index 00000000000..9c0c47013d1 --- /dev/null +++ b/cpp-client/deephaven/dhcore/src/interop/testapi/basic_interop_interactions.cc @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016-2024 Deephaven Data Labs and Patent Pending + */ +#include "deephaven/dhcore/interop/testapi/basic_interop_interactions.h" + +#include +#include "deephaven/dhcore/utility/utility.h" +#include "deephaven/third_party/fmt/format.h" + +using deephaven::dhcore::interop::ErrorStatus; +using deephaven::dhcore::interop::InteropBool; +using deephaven::dhcore::interop::StringHandle; +using deephaven::dhcore::interop::StringPool; +using deephaven::dhcore::interop::StringPoolHandle; +using deephaven::dhcore::interop::StringPoolBuilder; +using deephaven::dhcore::interop::testapi::BasicStruct; +using deephaven::dhcore::interop::testapi::NestedStruct; +using deephaven::dhcore::utility::MakeReservedVector; + +extern "C" { +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_Add( + int32_t a, int32_t b, int32_t *result) { + *result = a + b; +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddArrays( + const int32_t *a, const int32_t *b, int32_t length, int32_t *result) { + for (int32_t i = 0; i != length; ++i) { + result[i] = a[i] + b[i]; + } +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_Xor( + InteropBool a, InteropBool b, InteropBool *result) { + *result = InteropBool((bool)a ^ (bool)b); +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_XorArrays( + const InteropBool *a, const InteropBool *b, int32_t length, InteropBool *result) { + for (int32_t i = 0; i != length; ++i) { + result[i] = InteropBool((bool)a[i] ^ (bool)b[i]); + } +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_Concat( + const char *a, const char *b, + StringHandle *result_handle, StringPoolHandle *string_pool_handle) { + StringPoolBuilder builder; + auto text = std::string(a) + b; + *result_handle = builder.Add(text); + *string_pool_handle = builder.Build(); +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_ConcatArrays( + const char **a, const char **b, int32_t length, + deephaven::dhcore::interop::StringHandle *result_handles, + deephaven::dhcore::interop::StringPoolHandle *string_pool_handle) { + StringPoolBuilder builder; + for (int32_t i = 0; i != length; ++i) { + auto text = std::string(a[i]) + b[i]; + result_handles[i] = builder.Add(text); + } + *string_pool_handle = builder.Build(); +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddBasicStruct( + const BasicStruct *a, const BasicStruct *b, BasicStruct *result) { + *result = a->Add(*b); +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddBasicStructArrays( + const BasicStruct *a, const BasicStruct *b, int32_t length, BasicStruct *result) { + for (int32_t i = 0; i != length; ++i) { + result[i] = a[i].Add(b[i]); + } +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddNestedStruct( + const NestedStruct *a, const NestedStruct *b, NestedStruct *result) { + *result = a->Add(*b); +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_AddNestedStructArrays( + const NestedStruct *a, const NestedStruct *b, int32_t length, NestedStruct *result) { + for (int32_t i = 0; i != length; ++i) { + result[i] = a[i].Add(b[i]); + } +} + +void deephaven_dhcore_interop_testapi_BasicInteropInteractions_SetErrorIfLessThan( + int32_t a, int32_t b, ErrorStatus *error_status) { + error_status->Run([=]() { + if (a < b) { + auto message = fmt::format("{} < {}, which is not allowed", a, b); + throw std::runtime_error(message); + } + }); +} +} // extern "C" diff --git a/cpp-client/deephaven/tests/src/add_drop_test.cc b/cpp-client/deephaven/tests/src/add_drop_test.cc index 89901c09373..dbd2bce292f 100644 --- a/cpp-client/deephaven/tests/src/add_drop_test.cc +++ b/cpp-client/deephaven/tests/src/add_drop_test.cc @@ -6,7 +6,7 @@ namespace deephaven::client::tests { -TEST_CASE("Drop all columns", "[adddrop]") { +TEST_CASE("Drop some columns", "[adddrop]") { auto tm = TableMakerForTests::Create(); auto table = tm.Table(); auto t = table.Update("II = ii").Where("Ticker == `AAPL`"); diff --git a/cpp-client/deephaven/tests/src/attributes_test.cc b/cpp-client/deephaven/tests/src/attributes_test.cc index e0af4df9002..43684411a41 100644 --- a/cpp-client/deephaven/tests/src/attributes_test.cc +++ b/cpp-client/deephaven/tests/src/attributes_test.cc @@ -28,6 +28,6 @@ TEST_CASE("TableHandle Created By DoPut", "[attributes]") { CHECK(table.IsStatic()); // The columns all have the same size, so look at the source data for any one of them and get its size auto expected_size = static_cast(tm.ColumnData().ImportDate().size()); - CHECK(table.NumRows() == expected_size); + CHECK(expected_size == table.NumRows()); } } // namespace deephaven::client::tests diff --git a/cpp-client/deephaven/tests/src/join_test.cc b/cpp-client/deephaven/tests/src/join_test.cc index 0582991585a..fde79b7e481 100644 --- a/cpp-client/deephaven/tests/src/join_test.cc +++ b/cpp-client/deephaven/tests/src/join_test.cc @@ -135,8 +135,6 @@ TEST_CASE("Aj", "[join]") { TEST_CASE("Raj", "[join]") { auto tm = TableMakerForTests::Create(); - auto q = arrow::timestamp(arrow::TimeUnit::NANO, "UTC"); - TableHandle trades; { std::vector ticker_data = {"AAPL", "AAPL", "AAPL", "IBM", "IBM"}; @@ -206,15 +204,6 @@ TEST_CASE("Raj", "[join]") { std::vector> bid_size_data = {10, {}, {}, 5, 13}; std::vector> ask_data = {2.5, {}, {}, 105, 110}; std::vector> ask_size_data = {83, {}, {}, 47, 15}; - TableMaker table_maker; - table_maker.AddColumn("Ticker", ticker_data); - table_maker.AddColumn("Timestamp", timestamp_data); - table_maker.AddColumn("Price", price_data); - table_maker.AddColumn("Size", size_data); - table_maker.AddColumn("Bid", bid_data); - table_maker.AddColumn("BidSize", bid_size_data); - table_maker.AddColumn("Ask", ask_data); - table_maker.AddColumn("AskSize", ask_size_data); CompareTable( result, diff --git a/cpp-client/deephaven/tests/src/sort_test.cc b/cpp-client/deephaven/tests/src/sort_test.cc index 2c94ca72805..1bcf318c291 100644 --- a/cpp-client/deephaven/tests/src/sort_test.cc +++ b/cpp-client/deephaven/tests/src/sort_test.cc @@ -54,12 +54,6 @@ TEST_CASE("Sort temp Table", "[sort]") { auto sorted = temp_table.Sort(SortPair::Descending("IntValue3"), SortPair::Ascending("IntValue2")); - std::vector import_date_data = {"2017-11-01", "2017-11-01", "2017-11-01"}; - std::vector ticker_data = {"AAPL", "AAPL", "AAPL"}; - std::vector open_data = {22.1, 26.8, 31.5}; - std::vector close_data = {23.5, 24.2, 26.7}; - std::vector vol_data = {100000, 250000, 19000}; - std::vector sid0{8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7}; std::vector sid1{4, 4, 5, 5, 6, 6, 7, 7, 0, 0, 1, 1, 2, 2, 3, 3}; std::vector sid2{2, 2, 2, 2, 3, 3, 3, 3, 0, 0, 0, 0, 1, 1, 1, 1}; diff --git a/cpp-client/deephaven/tests/src/ungroup_test.cc b/cpp-client/deephaven/tests/src/ungroup_test.cc index 71621afe8bc..f946d171edc 100644 --- a/cpp-client/deephaven/tests/src/ungroup_test.cc +++ b/cpp-client/deephaven/tests/src/ungroup_test.cc @@ -5,15 +5,17 @@ #include "deephaven/tests/test_util.h" namespace deephaven::client::tests { -// TODO(kosak): This test is currently disabled (by membership in the [.] test group, because we -// don't yet deserialize the grouped column correctly. +// TODO(kosak): This test is currently disabled (by membership in the [.] test group). +// The reason is because each cell in the grouped column comes back as the Arrow type list, +// but the library does not currently know how to deserialize Arrow list types. TEST_CASE("Ungroup columns", "[.]") { auto tm = TableMakerForTests::Create(); auto table = tm.Table(); table = table.Where("ImportDate == `2017-11-01`"); - auto by_table = table.Where("Ticker == `AAPL`").View("Ticker", "Close").View("Ticker"); + auto by_table = table.Where("Ticker == `AAPL`").View("Ticker", "Close").By("Ticker"); + std::cout << by_table.Stream(true) << '\n'; auto ungrouped = by_table.Ungroup("Close"); std::vector ticker_data = {"AAPL"}; diff --git a/cpp-client/deephaven/tests/src/update_by_test.cc b/cpp-client/deephaven/tests/src/update_by_test.cc index e371a96f4da..79a9fd32738 100644 --- a/cpp-client/deephaven/tests/src/update_by_test.cc +++ b/cpp-client/deephaven/tests/src/update_by_test.cc @@ -154,7 +154,6 @@ TEST_CASE("UpdateBy: Multiple Ops", "[update_by]") { namespace { std::vector MakeTables(const Client &client) { - std::vector result; auto tm = client.GetManager(); auto static_table = MakeRandomTable(client).Update("Timestamp=now()"); auto ticking_table = tm.TimeTable(std::chrono::seconds(1)) diff --git a/cpp-client/deephaven/tests/src/validation_test.cc b/cpp-client/deephaven/tests/src/validation_test.cc index dcc07d12ede..2b2062db121 100644 --- a/cpp-client/deephaven/tests/src/validation_test.cc +++ b/cpp-client/deephaven/tests/src/validation_test.cc @@ -15,8 +15,6 @@ using deephaven::dhcore::utility::separatedList; namespace deephaven::client::tests { namespace { -void TestWheres(const TableHandleManager &scope); -void TestSelects(const TableHandleManager &scope); void TestWheresHelper(std::string_view what, const TableHandle &table, const std::vector &bad_wheres, const std::vector &good_wheres); @@ -26,19 +24,26 @@ void TestSelectsHelper(std::string_view what, const TableHandle &table, } // namespace TEST_CASE("Validate selects", "[validation]") { - auto tm = TableMakerForTests::Create(); - auto table = tm.Table(); - TestSelects(tm.Client().GetManager()); -} + std::vector> bad_selects = { + { "X = 3)" }, + { "S = `hello`", "T = java.util.regex.Pattern.quote(S)" }, // Pattern.quote not on whitelist + { "X = Math.min(3, 4)" } // Math.min not on whitelist + }; + std::vector> good_selects = { + {"X = 3"}, + {"S = `hello`", "T = S.length()"}, // instance methods of String ok + {"X = min(3, 4)"}, // "builtin" from GroovyStaticImports + {"X = isFinite(3)"}, // another builtin from GroovyStaticImports + }; -TEST_CASE("Validate wheres", "[validation]") { auto tm = TableMakerForTests::Create(); - auto table = tm.Table(); - TestWheres(tm.Client().GetManager()); + auto thm = tm.Client().GetManager(); + auto static_table = thm.EmptyTable(10) + .Update("X = 12", "S = `hello`"); + TestSelectsHelper("static Table", static_table, bad_selects, good_selects); } -namespace { -void TestWheres(const TableHandleManager &scope) { +TEST_CASE("Validate wheres", "[validation]") { std::vector bad_wheres = { "X > 3)", // syntax error "S = new String(`hello`)", // new not allowed @@ -55,11 +60,14 @@ void TestWheres(const TableHandleManager &scope) { "X in 3, 4, 5", }; - auto static_table = scope.EmptyTable(10) + auto tm = TableMakerForTests::Create(); + auto thm = tm.Client().GetManager(); + auto static_table = thm.EmptyTable(10) .Update("X = 12", "S = `hello`"); TestWheresHelper("static Table", static_table, bad_wheres, good_wheres); } +namespace { void TestWheresHelper(std::string_view what, const TableHandle &table, const std::vector &bad_wheres, const std::vector &good_wheres) { @@ -81,37 +89,18 @@ void TestWheresHelper(std::string_view what, const TableHandle &table, } } -void TestSelects(const TableHandleManager &scope) { - std::vector> bad_selects = { - { "X = 3)" }, - { "S = `hello`", "T = java.util.regex.Pattern.quote(S)" }, // Pattern.quote not on whitelist - { "X = Math.min(3, 4)" } // Math.min not on whitelist - }; - std::vector> good_selects = { - {"X = 3"}, - {"S = `hello`", "T = S.length()"}, // instance methods of String ok - {"X = min(3, 4)"}, // "builtin" from GroovyStaticImports - {"X = isFinite(3)"}, // another builtin from GroovyStaticImports - }; - auto static_table = scope.EmptyTable(10) - .Update("X = 12", "S = `hello`"); - TestSelectsHelper("static Table", static_table, bad_selects, good_selects); -} - void TestSelectsHelper(std::string_view what, const TableHandle &table, const std::vector> &bad_selects, const std::vector> &good_selects) { for (const auto &bs : bad_selects) { - SimpleOstringstream selection; - selection << separatedList(bs.begin(), bs.end()); try { (void)table.Select(bs); } catch (const std::exception &e) { - fmt::print(std::cerr, "{}: {}: Failed as expected with: {}\n", what, selection.str(), e.what()); + fmt::print(std::cerr, "{}: {}: Failed as expected with: {}\n", what, bs, e.what()); continue; } throw std::runtime_error(fmt::format("{}: {}: Expected to fail, but succeeded", - what, selection.str())); + what, bs)); } for (const auto &gs : good_selects) { diff --git a/cpp-client/deephaven/vcpkg-configuration.json b/cpp-client/deephaven/vcpkg-configuration.json index 1da16750d5f..e12dc32e3a6 100644 --- a/cpp-client/deephaven/vcpkg-configuration.json +++ b/cpp-client/deephaven/vcpkg-configuration.json @@ -1,7 +1,7 @@ { "default-registry": { "kind": "git", - "baseline": "0dc005fb66801c8a8266e81bd2cedb4d5501f30e", + "baseline": "1b5f7346612cd63910567df714d867f5b3fa8e3b", "repository": "https://github.com/microsoft/vcpkg" }, "registries": [ diff --git a/cpp-client/deephaven/vcpkg.json b/cpp-client/deephaven/vcpkg.json index 1731d32195a..d7ec195ee5f 100644 --- a/cpp-client/deephaven/vcpkg.json +++ b/cpp-client/deephaven/vcpkg.json @@ -12,6 +12,6 @@ "overrides": [ { "name": "arrow", "version": "13.0.0#1" }, - { "name": "protobuf", "version": "3.21.2" } + { "name": "protobuf", "version": "4.25.1" } ] }