From 3e7762a73c869db65ab58a44911b092603dccaae Mon Sep 17 00:00:00 2001 From: Torsten Kilias Date: Mon, 31 Aug 2026 11:56:29 +0200 Subject: [PATCH 01/32] Refactor: use upstream udf-runner-cpp base for Python VM --- exaudfclient/BUILD | 155 ++--- exaudfclient/MODULE.bazel | 13 +- exaudfclient/README.md | 10 +- exaudfclient/base/.bazelrc | 18 - exaudfclient/base/BUILD | 89 +-- exaudfclient/base/MODULE.bazel | 27 - exaudfclient/base/benchmark_container/BUILD | 10 - .../benchmark_container.cc | 135 ----- .../benchmark_container/benchmark_container.h | 27 - exaudfclient/base/build_integrated.py | 35 -- exaudfclient/base/create_binary_wrapper.sh | 13 - ...reate_binary_wrapper_stdout_to_bucketfs.sh | 23 - .../base/create_binary_wrapper_valgrind.sh | 13 - .../create_binary_wrapper_valgrind_massif.sh | 21 - exaudfclient/base/exaudflib/BUILD | 99 ---- exaudfclient/base/exaudflib/exascript.i | 136 ----- exaudfclient/base/exaudflib/impl/check.cc | 79 --- exaudfclient/base/exaudflib/impl/check.h | 17 - .../base/exaudflib/impl/exaudflib_main.cc | 297 ---------- exaudfclient/base/exaudflib/impl/global.cc | 73 --- exaudfclient/base/exaudflib/impl/global.h | 28 - .../base/exaudflib/impl/msg_conversion.cc | 71 --- .../base/exaudflib/impl/msg_conversion.h | 14 - .../base/exaudflib/impl/socket_high_level.cc | 528 ------------------ .../base/exaudflib/impl/socket_high_level.h | 22 - .../base/exaudflib/impl/socket_info.cc | 26 - .../base/exaudflib/impl/socket_info.h | 14 - .../base/exaudflib/impl/socket_low_level.cc | 101 ---- .../base/exaudflib/impl/socket_low_level.h | 15 - .../base/exaudflib/impl/swig/swig_factory.cc | 19 - .../impl/swig/swig_general_iterator.cc | 3 - .../impl/swig/swig_general_iterator.h | 28 - .../exaudflib/impl/swig/swig_meta_data.cc | 3 - .../base/exaudflib/impl/swig/swig_meta_data.h | 240 -------- .../impl/swig/swig_result_handler.cc | 3 - .../exaudflib/impl/swig/swig_result_handler.h | 282 ---------- .../impl/swig/swig_table_iterator.cc | 3 - .../exaudflib/impl/swig/swig_table_iterator.h | 346 ------------ exaudfclient/base/exaudflib/load_dynamic.h | 7 - .../swig/script_data_transfer_objects.cc | 465 --------------- .../swig/script_data_transfer_objects.h | 242 -------- .../script_data_transfer_objects_wrapper.cc | 103 ---- .../script_data_transfer_objects_wrapper.h | 74 --- .../base/exaudflib/swig/swig_common.cc | 2 - .../base/exaudflib/swig/swig_common.h | 186 ------ .../base/exaudflib/swig/swig_meta_data.cc | 2 - .../base/exaudflib/swig/swig_meta_data.h | 123 ---- .../exaudflib/swig/swig_result_handler.cc | 2 - .../base/exaudflib/swig/swig_result_handler.h | 72 --- .../exaudflib/swig/swig_table_iterator.cc | 2 - .../base/exaudflib/swig/swig_table_iterator.h | 79 --- exaudfclient/base/exaudflib/test/BUILD | 8 - .../script_data_transfer_objects_test.cpp | 260 --------- .../base/exaudflib/udf_plugin_interface.h | 19 - exaudfclient/base/exaudflib/vm/swig_vm.cc | 2 - exaudfclient/base/exaudflib/vm/swig_vm.h | 47 -- exaudfclient/base/load_dynamic.cc | 33 -- exaudfclient/base/protobuf_repository.bzl | 32 -- .../base/python/exascript_python_wrap.py | 6 +- exaudfclient/base/python/python3/BUILD | 30 +- .../base/replace_swig_import_helper.py | 50 -- exaudfclient/base/streaming_container/BUILD | 10 - .../streaming_container/streamingcontainer.cc | 344 ------------ .../streaming_container/streamingcontainer.h | 30 - exaudfclient/base/swig_factory/BUILD | 16 - exaudfclient/base/swig_factory/swig_factory.h | 18 - .../base/swig_factory/swig_factory_impl.cc | 19 - .../base/swig_factory/swig_factory_impl.h | 17 - exaudfclient/base/utils/BUILD | 12 - exaudfclient/base/utils/debug_message.h | 71 --- exaudfclient/base/utils/exceptions.h | 16 - exaudfclient/base/variables.bzl | 17 - exaudfclient/base/zmq_repository.bzl | 32 -- .../base/{exaudflib => }/zmqcontainer.proto | 4 +- .../diagrams/CTPGParserHandler.drawio.png | Bin 101619 -> 0 bytes .../diagrams/LegacyParserHandler.drawio.png | Bin 91552 -> 0 bytes ...alScriptOptionalsBuildingBlocks.drawio.png | Bin 26488 -> 0 bytes ...ScriptOptionsExtractorInterface.drawio.png | Bin 13749 -> 0 bytes ...iptOptionsParserHandlerSequence.drawio.png | Bin 41919 -> 0 bytes .../diagrams/V2ImportScriptFlow.drawio.png | Bin 150342 -> 0 bytes exaudfclient/docs/exaudfclient.drawio | 1 - exaudfclient/docs/exaudfclient.png | Bin 178663 -> 0 bytes exaudfclient/exa_udf_client.cc | 25 + .../exa_udf_client.h | 5 +- exaudfclient/exa_udfclient.cc | 4 +- .../exa_lib_loader.cc | 36 -- .../exa_lib_loader.h | 7 - .../exa_set_env.cc | 22 - .../exa_udfclient_binary_common/exa_set_env.h | 5 - .../exa_udf_base.cc | 49 -- .../exa_udf_base.h | 18 - .../exa_udf_client.cc | 37 -- .../exa_vm_factory.cc | 50 -- exaudfclient/exa_vm_factory.cc | 18 + .../exa_vm_factory.h | 6 +- .../{base => }/exaudfclient.template.sh | 4 +- exaudfclient/run_local.sh | 2 +- exaudfclient/variables.bzl | 12 +- .../base_test_build_run/Dockerfile | 2 +- .../base_test_build_run/Dockerfile | 2 +- .../base_test_build_run/Dockerfile | 2 +- .../base_test_build_run/Dockerfile | 2 +- .../base_test_build_run/Dockerfile | 2 +- .../base_test_build_run/Dockerfile | 2 +- .../base_test_build_run/Dockerfile | 2 +- 105 files changed, 151 insertions(+), 5652 deletions(-) delete mode 100644 exaudfclient/base/.bazelrc delete mode 100644 exaudfclient/base/MODULE.bazel delete mode 100644 exaudfclient/base/benchmark_container/BUILD delete mode 100644 exaudfclient/base/benchmark_container/benchmark_container.cc delete mode 100644 exaudfclient/base/benchmark_container/benchmark_container.h delete mode 100644 exaudfclient/base/build_integrated.py delete mode 100755 exaudfclient/base/create_binary_wrapper.sh delete mode 100755 exaudfclient/base/create_binary_wrapper_stdout_to_bucketfs.sh delete mode 100755 exaudfclient/base/create_binary_wrapper_valgrind.sh delete mode 100755 exaudfclient/base/create_binary_wrapper_valgrind_massif.sh delete mode 100644 exaudfclient/base/exaudflib/BUILD delete mode 100644 exaudfclient/base/exaudflib/exascript.i delete mode 100644 exaudfclient/base/exaudflib/impl/check.cc delete mode 100644 exaudfclient/base/exaudflib/impl/check.h delete mode 100644 exaudfclient/base/exaudflib/impl/exaudflib_main.cc delete mode 100644 exaudfclient/base/exaudflib/impl/global.cc delete mode 100644 exaudfclient/base/exaudflib/impl/global.h delete mode 100644 exaudfclient/base/exaudflib/impl/msg_conversion.cc delete mode 100644 exaudfclient/base/exaudflib/impl/msg_conversion.h delete mode 100644 exaudfclient/base/exaudflib/impl/socket_high_level.cc delete mode 100644 exaudfclient/base/exaudflib/impl/socket_high_level.h delete mode 100644 exaudfclient/base/exaudflib/impl/socket_info.cc delete mode 100644 exaudfclient/base/exaudflib/impl/socket_info.h delete mode 100644 exaudfclient/base/exaudflib/impl/socket_low_level.cc delete mode 100644 exaudfclient/base/exaudflib/impl/socket_low_level.h delete mode 100644 exaudfclient/base/exaudflib/impl/swig/swig_factory.cc delete mode 100644 exaudfclient/base/exaudflib/impl/swig/swig_general_iterator.cc delete mode 100644 exaudfclient/base/exaudflib/impl/swig/swig_general_iterator.h delete mode 100644 exaudfclient/base/exaudflib/impl/swig/swig_meta_data.cc delete mode 100644 exaudfclient/base/exaudflib/impl/swig/swig_meta_data.h delete mode 100644 exaudfclient/base/exaudflib/impl/swig/swig_result_handler.cc delete mode 100644 exaudfclient/base/exaudflib/impl/swig/swig_result_handler.h delete mode 100644 exaudfclient/base/exaudflib/impl/swig/swig_table_iterator.cc delete mode 100644 exaudfclient/base/exaudflib/impl/swig/swig_table_iterator.h delete mode 100644 exaudfclient/base/exaudflib/load_dynamic.h delete mode 100644 exaudfclient/base/exaudflib/swig/script_data_transfer_objects.cc delete mode 100644 exaudfclient/base/exaudflib/swig/script_data_transfer_objects.h delete mode 100644 exaudfclient/base/exaudflib/swig/script_data_transfer_objects_wrapper.cc delete mode 100644 exaudfclient/base/exaudflib/swig/script_data_transfer_objects_wrapper.h delete mode 100644 exaudfclient/base/exaudflib/swig/swig_common.cc delete mode 100644 exaudfclient/base/exaudflib/swig/swig_common.h delete mode 100644 exaudfclient/base/exaudflib/swig/swig_meta_data.cc delete mode 100644 exaudfclient/base/exaudflib/swig/swig_meta_data.h delete mode 100644 exaudfclient/base/exaudflib/swig/swig_result_handler.cc delete mode 100644 exaudfclient/base/exaudflib/swig/swig_result_handler.h delete mode 100644 exaudfclient/base/exaudflib/swig/swig_table_iterator.cc delete mode 100644 exaudfclient/base/exaudflib/swig/swig_table_iterator.h delete mode 100644 exaudfclient/base/exaudflib/test/BUILD delete mode 100644 exaudfclient/base/exaudflib/test/script_data_transfer_objects_test.cpp delete mode 100644 exaudfclient/base/exaudflib/udf_plugin_interface.h delete mode 100644 exaudfclient/base/exaudflib/vm/swig_vm.cc delete mode 100644 exaudfclient/base/exaudflib/vm/swig_vm.h delete mode 100644 exaudfclient/base/load_dynamic.cc delete mode 100644 exaudfclient/base/protobuf_repository.bzl delete mode 100644 exaudfclient/base/replace_swig_import_helper.py delete mode 100644 exaudfclient/base/streaming_container/BUILD delete mode 100644 exaudfclient/base/streaming_container/streamingcontainer.cc delete mode 100644 exaudfclient/base/streaming_container/streamingcontainer.h delete mode 100644 exaudfclient/base/swig_factory/BUILD delete mode 100644 exaudfclient/base/swig_factory/swig_factory.h delete mode 100644 exaudfclient/base/swig_factory/swig_factory_impl.cc delete mode 100644 exaudfclient/base/swig_factory/swig_factory_impl.h delete mode 100644 exaudfclient/base/utils/BUILD delete mode 100644 exaudfclient/base/utils/debug_message.h delete mode 100644 exaudfclient/base/utils/exceptions.h delete mode 100644 exaudfclient/base/variables.bzl delete mode 100644 exaudfclient/base/zmq_repository.bzl rename exaudfclient/base/{exaudflib => }/zmqcontainer.proto (98%) delete mode 100644 exaudfclient/docs/diagrams/CTPGParserHandler.drawio.png delete mode 100644 exaudfclient/docs/diagrams/LegacyParserHandler.drawio.png delete mode 100644 exaudfclient/docs/diagrams/OveralScriptOptionalsBuildingBlocks.drawio.png delete mode 100644 exaudfclient/docs/diagrams/ScriptOptionsExtractorInterface.drawio.png delete mode 100644 exaudfclient/docs/diagrams/ScriptOptionsParserHandlerSequence.drawio.png delete mode 100644 exaudfclient/docs/diagrams/V2ImportScriptFlow.drawio.png delete mode 100644 exaudfclient/docs/exaudfclient.drawio delete mode 100644 exaudfclient/docs/exaudfclient.png create mode 100644 exaudfclient/exa_udf_client.cc rename exaudfclient/{exa_udfclient_binary_common => }/exa_udf_client.h (88%) delete mode 100644 exaudfclient/exa_udfclient_binary_common/exa_lib_loader.cc delete mode 100644 exaudfclient/exa_udfclient_binary_common/exa_lib_loader.h delete mode 100644 exaudfclient/exa_udfclient_binary_common/exa_set_env.cc delete mode 100644 exaudfclient/exa_udfclient_binary_common/exa_set_env.h delete mode 100644 exaudfclient/exa_udfclient_binary_common/exa_udf_base.cc delete mode 100644 exaudfclient/exa_udfclient_binary_common/exa_udf_base.h delete mode 100644 exaudfclient/exa_udfclient_binary_common/exa_udf_client.cc delete mode 100644 exaudfclient/exa_udfclient_binary_common/exa_vm_factory.cc create mode 100644 exaudfclient/exa_vm_factory.cc rename exaudfclient/{exa_udfclient_binary_common => }/exa_vm_factory.h (64%) rename exaudfclient/{base => }/exaudfclient.template.sh (72%) diff --git a/exaudfclient/BUILD b/exaudfclient/BUILD index 08cfedf..dd91a04 100644 --- a/exaudfclient/BUILD +++ b/exaudfclient/BUILD @@ -1,147 +1,102 @@ +package(default_visibility = ["//visibility:public"]) load("//:variables.bzl", "VM_ENABLED_DEFINES") -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") +load("@rules_cc//cc:defs.bzl", "cc_binary") load("@rules_shell//shell:sh_library.bzl", "sh_library") - -VM_ENABLED_DEPS=select({ - "@exaudfclient_base//:benchmark": ["@exaudfclient_base//benchmark_container:benchmark_container"], - "//conditions:default": [] - }) + select({ - "@exaudfclient_base//:bash": ["@exaudfclient_base//streaming_container:streamingcontainer"], - "//conditions:default": [] - }) - -VM_PYTHON3_DEPS=select({ - "@exaudfclient_base//:python": ["@exaudfclient_base//python/python3:pythoncontainer"], - "//conditions:default": [] - }) - - -genrule( - name = "exaudflib_output_path_header", - srcs = ["@exaudfclient_base//:libexaudflib_complete.so"], - outs = ["exaudf_lib_output_path.h"], - cmd = ''' - echo "#define CUSTOM_LIBEXAUDFLIB_PATH \\"/exaudf/external/$(rlocationpath @exaudfclient_base//:libexaudflib_complete.so)\\"" > $@ - ''', -) - -## Here it may seem like exaudflib is linked twice; one at "deps" and another at "data" -## "deps" is basically used by Bazel for compile and link dependencies. -## "data" basically places the .so file into the runtime-runfiles-location -## so that it can be loaded using apis like load_library / load_symbol later -## therefore, it is not linked twice -cc_library( - name = "exa_udfclient_binary_common_lib", - srcs = [ - "exa_udfclient_binary_common/exa_lib_loader.cc", - "exa_udfclient_binary_common/exa_set_env.cc", - "exa_udfclient_binary_common/exa_udf_base.cc", - "exa_udfclient_binary_common/exa_udf_client.cc", - "exa_udfclient_binary_common/exa_vm_factory.cc", - "//:exaudflib_output_path_header", - ], - hdrs = [ - "exa_udfclient_binary_common/exa_lib_loader.h", - "exa_udfclient_binary_common/exa_set_env.h", - "exa_udfclient_binary_common/exa_udf_base.h", - "exa_udfclient_binary_common/exa_udf_client.h", - "exa_udfclient_binary_common/exa_vm_factory.h", - ], - deps = [ - "@exaudfclient_base//exaudflib:header", - "@exaudfclient_base//utils:utils", - "@exaudfclient_base//exaudflib:exaudflib-deps", - ] + VM_ENABLED_DEPS + VM_PYTHON3_DEPS, - defines = VM_ENABLED_DEFINES, - data = ["@exaudfclient_base//:libexaudflib_complete.so"], +config_setting( + name = "python", + define_values = {"python": "true"}, ) cc_binary( name = "exaudfclient_bin", srcs = [ "exa_udfclient.cc", + "exa_udf_client.cc", + "exa_udf_client.h", + "exa_vm_factory.cc", + "exa_vm_factory.h", "@exaudfclient_base//:load_dynamic", ], linkopts = ["-ldl"], - deps = [":exa_udfclient_binary_common_lib"], - data = ["@exaudfclient_base//:libexaudflib_complete.so"] + deps = [ + "//base/python/python3:pythoncontainer", + "@exaudfclient_base//exa_udfclient_binary_common:exa_udfclient_binary_common_lib", + ], + defines = VM_ENABLED_DEFINES, + data = ["@exaudfclient_base//:libexaudflib_complete.so"], ) -## The purpose of the static binaries is to verify if the linker namespace test work correctly. -## It is crucial that all linker symbols of exaudflib and all it's dependency are loaded into a new linker namespace, -## so that the user can load it's own versions of those dependencies without any conflict. -## With this binary we simulate an error in our build system, that is a direct dependency to protobuf/zmq, -## which then must be detected with the linker namespace tests: -## test/linker_namespace_sanity/linker_namespace_sanity.py checks the wrong configuration -## Besides this the test under test/python3/all/linker_namespace.py checks the normal build, which expects -## not to find any occurrence of the dependencies (protobuf/zmq) in the primary linker namespace. -## -## We need to explicitly declare the dependency of protobuf/zmq here, as the exaudflib is a static lib (//exaudflib:exaudflib) -## and hence does not contain dependency information. We cannot declare the shared lib (:exaudflib_complete.so) -## as dependency as it is a binary for bazel. - cc_binary( name = "exaudfclient_static_bin", srcs = [ "exa_udfclient.cc", + "exa_udf_client.cc", + "exa_udf_client.h", + "exa_vm_factory.cc", + "exa_vm_factory.h", "@exaudfclient_base//:load_dynamic", ], linkopts = ["-ldl"], deps = [ - ":exa_udfclient_binary_common_lib", - "@zmq//:zmq", + "//base/python/python3:pythoncontainer", + "@exaudfclient_base//exa_udfclient_binary_common:exa_udfclient_binary_common_lib", "@protobuf//:protobuf", + "@zmq//:zmq", ], + defines = VM_ENABLED_DEFINES, data = ["@exaudfclient_base//:libexaudflib_complete.so"], ) -# Workaround for the hardcoded paths in exaudfclient for libexaudflib_complete.so and python_ext_dataframe.cc -# - libexaudflib_complete.so and python_ext_dataframe.cc get dynamically loaded, therefore the exaudfclient needs to know their paths -# - Most flexible way to provides these paths would environment variables -# - The exasol database can't provide these paths, because they depend on the container -# - A workaround to provide these paths would be wrapper bash script which set these environment variables -# - For performance reason, we can not wrap the binary into a shell script, as such this is only for local debugging and testing -# and we hardcode the paths for the production container - sh_library( name = "wrapper_generator_bin", - srcs=select({ + srcs = select({ "@exaudfclient_base//:valgrind_wrapper": ["@exaudfclient_base//:create_binary_wrapper_valgrind.sh"], "@exaudfclient_base//:valgrind_massif_wrapper": ["@exaudfclient_base//:create_binary_wrapper_valgrind_massif.sh"], "@exaudfclient_base//:stdout_to_bucketfs": ["@exaudfclient_base//:create_binary_wrapper_stdout_to_bucketfs.sh"], - "//conditions:default": ["//base:create_binary_wrapper.sh"] - }) + "//conditions:default": ["@exaudfclient_base//:create_binary_wrapper.sh"], + }), ) -SLOW_WRAPPER_BINARY="""$(location //:wrapper_generator_bin) "$(location exaudfclient_bin)" "$(location exaudfclient)" "$(location @exaudfclient_base//:exaudfclient.template.sh)" """ -FAST_BINARY="""cp "$(location exaudfclient_bin)" "$(location exaudfclient)" """ -CREATE_BINARY_SCRIPT=select({ - "@exaudfclient_base//:fast_binary": FAST_BINARY, - "@exaudfclient_base//:slow_wrapper": SLOW_WRAPPER_BINARY, - "//conditions:default": FAST_BINARY - }) +SLOW_WRAPPER_BINARY = """$(location :wrapper_generator_bin) "$(location :exaudfclient_bin)" "$@" "$(location :exaudfclient.template.sh)" """ +FAST_BINARY = """cp "$(location :exaudfclient_bin)" "$@" """ +CREATE_BINARY_SCRIPT = select({ + "@exaudfclient_base//:fast_binary": FAST_BINARY, + "@exaudfclient_base//:slow_wrapper": SLOW_WRAPPER_BINARY, + "//conditions:default": FAST_BINARY, +}) + genrule( name = "exaudfclient", cmd = CREATE_BINARY_SCRIPT, outs = ["exaudfclient"], - srcs = [":exaudfclient_bin", "@exaudfclient_base//:libexaudflib_complete.so", "@exaudfclient_base//:exaudfclient.template.sh", "//:wrapper_generator_bin"], - output_to_bindir = True + srcs = [ + ":exaudfclient_bin", + ":exaudfclient.template.sh", + ":wrapper_generator_bin", + "@exaudfclient_base//:libexaudflib_complete.so", + ], + output_to_bindir = True, ) -SLOW_WRAPPER_STATIC_BINARY="""$(location //:wrapper_generator_bin) "$(location exaudfclient_static_bin)" "$(location exaudfclient_static)" "$(location @exaudfclient_base//:exaudfclient.template.sh)" """ -FAST_BINARY_STATIC="""cp "$(location exaudfclient_static_bin)" "$(location exaudfclient_static)" """ -CREATE_STATIC_BINARY_SCRIPT=select({ - "@exaudfclient_base//:fast_binary": FAST_BINARY_STATIC, - "@exaudfclient_base//:slow_wrapper": SLOW_WRAPPER_STATIC_BINARY, - "//conditions:default": FAST_BINARY_STATIC - }) +SLOW_WRAPPER_STATIC_BINARY = """$(location :wrapper_generator_bin) "$(location :exaudfclient_static_bin)" "$@" "$(location :exaudfclient.template.sh)" """ +FAST_BINARY_STATIC = """cp "$(location :exaudfclient_static_bin)" "$@" """ +CREATE_STATIC_BINARY_SCRIPT = select({ + "@exaudfclient_base//:fast_binary": FAST_BINARY_STATIC, + "@exaudfclient_base//:slow_wrapper": SLOW_WRAPPER_STATIC_BINARY, + "//conditions:default": FAST_BINARY_STATIC, +}) genrule( name = "exaudfclient_static", cmd = CREATE_STATIC_BINARY_SCRIPT, outs = ["exaudfclient_static"], - srcs = [":exaudfclient_static_bin", "@exaudfclient_base//:libexaudflib_complete.so", "@exaudfclient_base//:exaudfclient.template.sh", "//:wrapper_generator_bin"], - output_to_bindir = True + srcs = [ + ":exaudfclient_static_bin", + ":exaudfclient.template.sh", + ":wrapper_generator_bin", + "@exaudfclient_base//:libexaudflib_complete.so", + ], + output_to_bindir = True, ) diff --git a/exaudfclient/MODULE.bazel b/exaudfclient/MODULE.bazel index b445d66..72dee0a 100644 --- a/exaudfclient/MODULE.bazel +++ b/exaudfclient/MODULE.bazel @@ -1,16 +1,19 @@ module(name="exaudfclient", version = "1.0") bazel_dep(name = "exaudfclient_base", version = "1.0.0") -#For now, the Bazel Modul "exaudfclient_base" is stored in subdirectory "base". -#Later we might fetch it via Http or Git (after splitting up script-languages repository) -local_path_override(module_name="exaudfclient_base", path="base") +git_override( + module_name = "exaudfclient_base", + remote = "https://github.com/exasol/udf-runner-cpp.git", + commit = "b3a8c204a2555b373c66110d5e8301a374b32a6a", + strip_prefix = "udf-runner-cpp/v1/base", +) bazel_dep(name = "rules_cc", version = "0.2.22") bazel_dep(name = "rules_shell", version = "0.8.0") -numpy_local_repository = use_repo_rule("@exaudfclient_base//:python_repository.bzl", "numpy_local_repository") +numpy_local_repository = use_repo_rule("//base:python_repository.bzl", "numpy_local_repository") numpy_local_repository(name = "numpy") -python_local_repository = use_repo_rule("@exaudfclient_base//:python_repository.bzl", "python_local_repository") +python_local_repository = use_repo_rule("//base:python_repository.bzl", "python_local_repository") python_local_repository(name = "python3", python_version="python3") zmq_local_repository = use_repo_rule("@exaudfclient_base//:zmq_repository.bzl", "zmq_local_repository") diff --git a/exaudfclient/README.md b/exaudfclient/README.md index b95fb58..986c4a7 100644 --- a/exaudfclient/README.md +++ b/exaudfclient/README.md @@ -25,7 +25,7 @@ For the language support: ## Start a build -The exaudfclient is a multi-language project. Therefore, we are using [Bazel](https://docs.bazel.build/versions/master/bazel-overview.html) as build system, because it provides build support for many languages and allows to mix these languages. Because the exaudfclient has language bindings to Python 2/3 and R, we need specify where Bazel can find the corresponding library and header files. This is done by environment variables. +The exaudfclient is a Python project with a C++ runner. It uses [Bazel](https://docs.bazel.build/versions/master/bazel-overview.html) to build the local Python VM against the shared runner base from `exasol/udf-runner-cpp`. Set the Python library and header locations through environment variables. For executing the build locally, you can use the script @@ -43,9 +43,7 @@ Both build script can receive parameters, such as Bazel commandline parameter, B With Bazel defines you can specify which language support is actually compiled into you exaudfclient executbale. The currently supported defines are - --define r=true --define python=true - --define benchmark=true # This language is only for test and development purpose and benchmarks the performance of the C++ Implementation The main targets is //:exaudfclient. @@ -58,15 +56,13 @@ Bazel allows to query the dependencies of a target. Furthermore, it can export t # How is the exaudfclient structured? -The exaudfclient consists mainly out of three parts the main function in [exa_udfclient.cc](exa_udfclient.cc), the libexaudf and the language implementations. The first part the main function actually only loads the two other parts. However, in this case it is important how it loads the two other parts, because we need the libexaudf in a different linker namespace than the language implementation to prevent library conflicts. The libexaudf uses [ZeroMQ](http://zeromq.org/) and [Protobuf](https://developers.google.com/protocol-buffers/) to communicate with the Exsol Database, but UDFs could be use the same libraries in a different version which would lead to library conflict. The following figure shows the dependencies between the components. - -![exaudfclient dependencies](docs/exaudfclient.png) +The local code contains the main function in [exa_udfclient.cc](exa_udfclient.cc) and the Python VM. The shared libexaudf transport, loader, ZeroMQ, and Protobuf dependencies come from the pinned `exasol/udf-runner-cpp` Bazel module and load in a separate linker namespace. The usage of multiple linker namespace requires some precautions in the build process and in the implementation. ## Precautions in the build process -In the build process you need to be cautious which libraries you link together and that no link leaks symbols from a library in one namespace to a library in the other namespace. Furthermore, you have to build a shared library with all dependency linked to it as output target. In our case, we have two main output targets: //:exaudfclient and //:libexaudflib.so. Both get loaded into different linker namespaces. The language containers live in the same namespace as //:exaudfclient. This namespace must not know anything about protobuf and zeromq, because a language container may load protobuf or zeromq in a different version. Protobuf and zeromq are only known in the namespace of //:libexaudflib.so. The target //:libexaudflib.so depends on //base/exaudflib:exaudflib which contains the logic of the exaudflib. You must not depend on //base/exaudflib:exaudflib in //:exaudfclient or a language container, because this would leak zeromq and protobuf. If you need other dependencies of //base/exaudflib:exaudflib that do not depend on protobuf or zeromq, such as //base/exaudflib:script_data_transfer_objects or //base/exaudflib:script_data_transfer_objects_wrapper, use their target directly, the collection of libraries //base/exaudflib:exaudflib-deps, or the collection of headers //base/exaudflib:header. +Do not link the Python VM directly against the shared transport implementation: use only the `@exaudfclient_base//exaudflib:header` and `@exaudfclient_base//exaudflib:exaudflib-deps` targets. This keeps ZeroMQ and Protobuf out of the Python VM linker namespace. ## Precautions in the implementations diff --git a/exaudfclient/base/.bazelrc b/exaudfclient/base/.bazelrc deleted file mode 100644 index c6d0048..0000000 --- a/exaudfclient/base/.bazelrc +++ /dev/null @@ -1,18 +0,0 @@ -build --lockfile_mode=off --copt='-std=c++17' --force_pic --action_env=PROTOBUF_BIN --action_env=PROTOBUF_LIBRARY_PREFIX --action_env=PROTOBUF_INCLUDE_PREFIX -build:benchmark --define benchmark=true -build:python --define python=true --action_env=NUMPY_PREFIX --action_env=PYTHON3_SYSPATH --action_env=PYTHON3_PREFIX --action_env=PYTHON3_VERSION -build:debug-build --sandbox_debug --config=verbose -build:no-symlinks --symlink_prefix=/ -build:asan --strip=never -build:asan --copt -fsanitize=address -build:asan --copt -DADDRESS_SANITIZER -build:asan --copt -O1 -build:asan --copt -g -build:asan --copt -fno-omit-frame-pointer -build:asan --linkopt -fsanitize=address -build:asan -c dbg -build:valgrind --copt -O1 -build:valgrind -c dbg -build:valgrind --copt -g -build:valgrind --strip=never -build:valgrind --copt -DVALGRIND_ACTIVE diff --git a/exaudfclient/base/BUILD b/exaudfclient/base/BUILD index 5f857bf..fbceeaf 100644 --- a/exaudfclient/base/BUILD +++ b/exaudfclient/base/BUILD @@ -1,90 +1,3 @@ - package(default_visibility = ["//visibility:public"]) -exports_files(["build_integrated.py", - "create_binary_wrapper.sh", "create_binary_wrapper_valgrind.sh", - "create_binary_wrapper_valgrind_massif.sh", "exaudfclient.template.sh", - "replace_swig_import_helper.py"]) - -load("//:variables.bzl", "VM_ENABLED_DEFINES") -load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") - -config_setting( - name = "benchmark", - define_values = {"benchmark": "true"}, -) - -config_setting( - name = "python", - define_values = {"python": "true"}, -) - -config_setting( - name = "bash", - define_values = {"bash": "true"}, -) - -config_setting( - name = "fast_binary", - define_values = { - "binary_type": "fast_binary", - }, -) - -config_setting( - name = "slow_wrapper", - define_values = { - "binary_type": "slow_wrapper", - }, -) - -config_setting( - name = "valgrind_wrapper", - define_values = { - "wrapper_type": "valgrind_wrapper", - }, -) - -config_setting( - name = "valgrind_massif_wrapper", - define_values = { - "wrapper_type": "valgrind_massif_wrapper", - }, -) - -config_setting( - name = "stdout_to_bucketfs", - define_values = { - "wrapper_type": "stdout_to_bucketfs", - }, -) - -config_setting( - name = "plugin_client", - define_values = {"plugin_client": "true"}, -) - -cc_library( - name = "load_dynamic", - srcs = [ - "load_dynamic.cc" - ], - deps = ["//exaudflib:header", "//utils:utils", "//exaudflib:exaudflib-deps"], - defines = VM_ENABLED_DEFINES, -) - -# Using cc_binary to build a shared library as output target is a workaround, because -# Bazel's cc_library are only intermediate stages and can't be used as output target. -# It is necessary to include //exaudflib:exaudflib into deps and srcs, because -# otherwise dlmopen won't find the symbols of exaudflib and its dependencies. The target //exaudflib:exaudflib-deps -# won't work either, because it only contains the libraries as dependencies. -# Bazel builts a static library (.a) and a dynamic library (.so) out of exaudflib:exaudflib. -# In the libexaudflib_complete.so-2.params, we saw that Bazel uses both libraries to built libexaudflib_complete.so. -# Experiments have shown that we get missing symbols during loading libexaudflib_complete.so, if we only built the static library. -cc_binary( - name = "libexaudflib_complete.so", - linkshared = 1, - srcs = ["//exaudflib:exaudflib"], - deps = ["//exaudflib:exaudflib"], - defines = VM_ENABLED_DEFINES, -) +exports_files(["python_repository.bzl"]) diff --git a/exaudfclient/base/MODULE.bazel b/exaudfclient/base/MODULE.bazel deleted file mode 100644 index 8cb18b7..0000000 --- a/exaudfclient/base/MODULE.bazel +++ /dev/null @@ -1,27 +0,0 @@ -module(name="exaudfclient_base", version = "1.0") - -bazel_dep(name = "bazel_skylib", version = "1.7.1") -bazel_dep(name = "googletest", version = "1.15.0") -bazel_dep(name = "rules_cc", version = "0.2.22") - -# Since Bazel >8 the Python hermetic build rules must not run as root -# However, since the UDF client is built as root in a docker container -# we must disable this behavior. The only way is to configure the Python hermetic toolchain -bazel_dep(name = "rules_python", version = "1.7.0") - -python = use_extension("@rules_python//python/extensions:python.bzl", "python") -python.defaults(python_version = "3.11") -python.toolchain(python_version = "3.11", ignore_root_user_error = True,) - - -numpy_local_repository = use_repo_rule("@exaudfclient_base//:python_repository.bzl", "numpy_local_repository") -numpy_local_repository(name = "numpy") - -python_local_repository = use_repo_rule("@exaudfclient_base//:python_repository.bzl", "python_local_repository") -python_local_repository(name = "python3", python_version="python3") - -zmq_local_repository = use_repo_rule("@exaudfclient_base//:zmq_repository.bzl", "zmq_local_repository") -zmq_local_repository(name = "zmq") - -protobuf_local_repository = use_repo_rule("@exaudfclient_base//:protobuf_repository.bzl", "protobuf_local_repository") -protobuf_local_repository(name = "protobuf") diff --git a/exaudfclient/base/benchmark_container/BUILD b/exaudfclient/base/benchmark_container/BUILD deleted file mode 100644 index c591e6a..0000000 --- a/exaudfclient/base/benchmark_container/BUILD +++ /dev/null @@ -1,10 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@rules_cc//cc:defs.bzl", "cc_library") - -cc_library( - name = "benchmark_container", - srcs = ["benchmark_container.cc","benchmark_container.h"], - hdrs = ["benchmark_container.h"], - deps = ["//exaudflib:exaudflib-deps","//exaudflib:header", "//utils:utils"] -) diff --git a/exaudfclient/base/benchmark_container/benchmark_container.cc b/exaudfclient/base/benchmark_container/benchmark_container.cc deleted file mode 100644 index 92de436..0000000 --- a/exaudfclient/base/benchmark_container/benchmark_container.cc +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef ENABLE_BENCHMARK_VM -#define ENABLE_BENCHMARK_VM -#endif - -#include "utils/debug_message.h" -#include "benchmark_container.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -using namespace SWIGVMContainers; -using namespace std; - -BenchmarkVM::BenchmarkVM(bool checkOnly) - : meta(), inp(), outp(&inp) - -{ - if (meta.inputType() != MULTIPLE - || meta.outputType() != MULTIPLE) - { - throw SWIGVM::exception("BENCHMARK language container only support SET-EMITS UDFs"); - } -} - -void BenchmarkVM::shutdown() -{ -} - -bool BenchmarkVM::run() -{ - DBG_FUNC_BEGIN(cerr); - cerr << "Input Columns:" << endl; - for (unsigned int col = 0; colempty()){ - count++; - } - } - break; - default: - break; - } - } - hasNext = inp.next(); - } while (hasNext); - cerr << "End fetch" << endl; - } catch (std::exception& err) { - lock_guard lock(exception_msg_mtx); - exception_msg = err.what(); - cerr << "Exception BenchmarkVM::run " << exception_msg << endl; - } - - try { - cerr << "Begin emit" << endl; - string str1 = string("test1"); - outp.setString(0,str1.c_str(),strlen(str1.c_str())); - outp.next(); - string str2 = string("test2"); - outp.setString(0,str2.c_str(),strlen(str2.c_str())); - outp.next(); - outp.flush(); - cerr << "End emit" << endl; - } catch (std::exception& err) { - lock_guard lock(exception_msg_mtx); - exception_msg = err.what(); - cerr << "Exception BenchmarkVM::run " << exception_msg << endl; - } - - if (exception_msg.size() > 0) { - throw SWIGVM::exception(exception_msg.c_str()); - } - - } catch (std::exception& ex) { - lock_guard lock(exception_msg_mtx); - exception_msg = ex.what(); - cerr << "Exception BenchmarkVM::run " << exception_msg << endl; - } - DBG_FUNC_END(cerr); - return true; // done -} - -const char* BenchmarkVM::singleCall(single_call_function_id_e fn, const ExecutionGraph::ScriptDTO& args) -{ - throw SWIGVM::exception("singleCall not supported for the STREAMING language container"); -} diff --git a/exaudfclient/base/benchmark_container/benchmark_container.h b/exaudfclient/base/benchmark_container/benchmark_container.h deleted file mode 100644 index e107f4b..0000000 --- a/exaudfclient/base/benchmark_container/benchmark_container.h +++ /dev/null @@ -1,27 +0,0 @@ -#include "exaudflib/vm/swig_vm.h" -#include "exaudflib/swig/swig_meta_data.h" -#include "exaudflib/swig/swig_result_handler.h" -#include "exaudflib/swig/swig_table_iterator.h" - -using namespace SWIGVMContainers; -using namespace std; - - -class BenchmarkVM: public SWIGVM { - public: - struct exception: SWIGVM::exception { - exception(const char *reason): SWIGVM::exception(reason) { } - virtual ~exception() throw() { } - }; - BenchmarkVM(bool checkOnly); - virtual ~BenchmarkVM() {}; - virtual void shutdown(); - virtual bool run(); - virtual const char* singleCall(single_call_function_id_e fn, const ExecutionGraph::ScriptDTO& args); - virtual bool useZmqSocketLocks() {return true;} - private: - SWIGMetadata meta; - SWIGTableIterator inp; - SWIGResultHandler outp; - void importScripts(); -}; \ No newline at end of file diff --git a/exaudfclient/base/build_integrated.py b/exaudfclient/base/build_integrated.py deleted file mode 100644 index c43f0bc..0000000 --- a/exaudfclient/base/build_integrated.py +++ /dev/null @@ -1,35 +0,0 @@ -import sys - - -def build_integrated(target, source): - assert(len(target) == 1 and len(source) > 0) - builddir = '.' - RE='/usr' - - output = [] - for fname in source: - fname_short = str(fname) - if fname_short.startswith(builddir): - fname_short = fname_short[len(builddir):] - fvar = 'integrated_' + fname_short.lower().replace('.', '_').replace('/', '_') - flines = [] - with open(str(fname)) as fname_file: - for line in fname_file: - line = line.replace(", PACKAGE='exascript_r'", '') - line = line.replace('\\', '\\\\') - line = line.replace(r'"', r'\"') - line = line.replace('\r', r'\r') - line = line.replace('\n', r'\n') - line = line.replace('RUNTIME_PATH', RE) - flines.append(line) - output.append('static const char *' + fvar + ' = "' + ''.join(flines) + '";\n') - with open(str(target[0]), 'w') as fd: - fd.write(''.join(output)) - return 0 - - -if __name__ == "__main__": - if len(sys.argv) < 3: - print('Usage: build_integrated.py target source_1 source_2 ...') - sys.exit(1) - build_integrated(sys.argv[1:2], sys.argv[2:]) diff --git a/exaudfclient/base/create_binary_wrapper.sh b/exaudfclient/base/create_binary_wrapper.sh deleted file mode 100755 index c00a66e..0000000 --- a/exaudfclient/base/create_binary_wrapper.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -o errexit -set -o pipefail -CLIENT_BINARY=$1 -CLIENT_WRAPPER=$2 -WRAPPER_TEMPLATE=$3 -touch "$CLIENT_WRAPPER" - -{ -cat "$WRAPPER_TEMPLATE" -echo -echo ./"$(basename "$CLIENT_BINARY")" '$*' -} >> "$CLIENT_WRAPPER" \ No newline at end of file diff --git a/exaudfclient/base/create_binary_wrapper_stdout_to_bucketfs.sh b/exaudfclient/base/create_binary_wrapper_stdout_to_bucketfs.sh deleted file mode 100755 index 4db4327..0000000 --- a/exaudfclient/base/create_binary_wrapper_stdout_to_bucketfs.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash -# shellcheck disable=SC2016 - -set -o errexit -set -o pipefail -CLIENT_BINARY=$1 -CLIENT_WRAPPER=$2 -WRAPPER_TEMPLATE=$3 -touch "$CLIENT_WRAPPER" - -{ -cat "$WRAPPER_TEMPLATE" -echo -echo 'NAME="$1"' -#Ignore shellcheck rule, change is too risky. -#shellcheck disable=SC2001 -echo 'OUTPUT_FILE="/tmp/$(echo "$NAME" | sed s#[/:]##g)"' -echo "./$(basename "$CLIENT_BINARY")" '"$@"' '&> "$OUTPUT_FILE"' -echo 'UPLOAD="curl --fail -X PUT -T $OUTPUT_FILE http://w:write@localhost:6583/default$OUTPUT_FILE"' -echo 'echo "$UPLOAD"' -echo '"$UPLOAD"' - -} >> "$CLIENT_WRAPPER" \ No newline at end of file diff --git a/exaudfclient/base/create_binary_wrapper_valgrind.sh b/exaudfclient/base/create_binary_wrapper_valgrind.sh deleted file mode 100755 index 5fb10a1..0000000 --- a/exaudfclient/base/create_binary_wrapper_valgrind.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -set -o errexit -set -o pipefail -CLIENT_BINARY=$1 -CLIENT_WRAPPER=$2 -WRAPPER_TEMPLATE=$3 -touch "$CLIENT_WRAPPER" - -{ -cat "$WRAPPER_TEMPLATE" -echo -echo valgrind "./$(basename "$CLIENT_BINARY")" '$*' -} >> "$CLIENT_WRAPPER" \ No newline at end of file diff --git a/exaudfclient/base/create_binary_wrapper_valgrind_massif.sh b/exaudfclient/base/create_binary_wrapper_valgrind_massif.sh deleted file mode 100755 index 3446605..0000000 --- a/exaudfclient/base/create_binary_wrapper_valgrind_massif.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash -# shellcheck disable=SC2016 - -set -o errexit -set -o pipefail -CLIENT_BINARY=$1 -CLIENT_WRAPPER=$2 -WRAPPER_TEMPLATE=$3 -touch "$CLIENT_WRAPPER" -{ -cat "$WRAPPER_TEMPLATE" -echo -echo 'NAME="$1"' -#Ignore shellcheck rule, change is too risky. -#shellcheck disable=SC2001 -echo 'MASSIF_FILE="/tmp/$(echo "$NAME" | sed s#[/:]##g)"' -echo valgrind --tool=massif --massif-out-file='"$MASSIF_FILE"' "./$(basename "$CLIENT_BINARY")" '"$@"' -echo 'UPLOAD="curl --fail -X PUT -T $MASSIF_FILE http://w:write@localhost:6583/default$MASSIF_FILE"' -echo 'echo "$UPLOAD"' -echo '"$UPLOAD"' -} >> "$CLIENT_WRAPPER" \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/BUILD b/exaudfclient/base/exaudflib/BUILD deleted file mode 100644 index 9e6274d..0000000 --- a/exaudfclient/base/exaudflib/BUILD +++ /dev/null @@ -1,99 +0,0 @@ -package(default_visibility = ["//visibility:public"]) -exports_files(["exascript.i"]) - -load("//:variables.bzl", "VM_ENABLED_DEFINES") -load("@rules_cc//cc:defs.bzl", "cc_library") - -cc_library( - name = "script_data_transfer_objects", - srcs = ["swig/script_data_transfer_objects.cc","swig/script_data_transfer_objects.h"], - hdrs = ["swig/script_data_transfer_objects.h"], - copts= select({ - "//:benchmark": ["-fno-lto"], - "//conditions:default": [] - }), - # We deactivate link time optimization for benchmark, - # because otherwise we get linker/compiler error while linking/compiling exaudfclient - # Benchmark causes this, because it doesn't refer it its implementation. -) - -cc_library( - name = "script_data_transfer_objects_wrapper", - srcs = ["swig/script_data_transfer_objects_wrapper.cc","swig/script_data_transfer_objects_wrapper.h"], - deps = [":script_data_transfer_objects"], - hdrs = ["swig/script_data_transfer_objects_wrapper.h"], - copts= select({ - "//:benchmark": ["-fno-lto"], - "//conditions:default": [] - }), - # We deactivate link time optimization for benchmark, - # because otherwise we get linker/compiler error while linking/compiling exaudfclient - # Benchmark causes this, because it doesn't refer it its implementation. -) - -# A collection target for the case that language container want to include all public headers of exaudflib -cc_library( - name = "header", - hdrs = [ - "udf_plugin_interface.h", "load_dynamic.h", "vm/swig_vm.h", - "swig/swig_common.h", "swig/swig_meta_data.h", "swig/swig_result_handler.h", "swig/swig_table_iterator.h" - ], -) - -# A collection target for the case that language container want to depent on all public libraries of exaudflib -# which won't leak protobuf through linker namespaces. Caution: Can't be used for the target libexaudflib-complete.so, -# because this target declares the libraries only as deps. -cc_library( #TODO might be not working as expected - name = "exaudflib-deps", - deps = [":script_data_transfer_objects",":script_data_transfer_objects_wrapper"], -) - -genrule( - name = "zmqcontainer_proto", - cmd = """ - TMPDIR=`mktemp -d` - cp $< "$$TMPDIR" - (cd "$$TMPDIR" - $$PROTOBUF_BIN -I. zmqcontainer.proto --cpp_out=.) - cp "$$TMPDIR"/zmqcontainer.pb.cc $(location zmqcontainer.pb.cc) - cp "$$TMPDIR"/zmqcontainer.pb.h $(location zmqcontainer.pb.h)""", - outs = ["zmqcontainer.pb.cc","zmqcontainer.pb.h"], - srcs = ["zmqcontainer.proto"] -) - -cc_library( - name = "zmqcontainer", - hdrs = [":zmqcontainer_proto"], - srcs = [":zmqcontainer_proto"], - deps = ["@protobuf//:protobuf"], - copts = ["-DNDEBUG=1"] #We use the protobuf shared library compiled with NDEBUG=1 (the conda package is the release version). We need to set NDEBUG=1, otherwise some functions are not visisble for the dependent libraries (compiled inline for NDEBUG=1, compiled as global function otherwise). - -) - -# Do not depend on this library in the langauge container or exaudfclient. -# The only target which must depend on it is //:libexaudflib-complete.so. -# If you depend on this target you will load protobuf into your linker namespace -# which might cause problems with tensorflow. If you need -# "//exaudflib:script_data_transfer_objects" or -# "//exaudflib:script_data_transfer_objects_wrapper" in the language container -# depend directly on them or depend on exaudflib-deps -cc_library( - name = "exaudflib", - srcs = ["vm/swig_vm.cc", - "swig/swig_common.cc", "swig/swig_meta_data.cc", "swig/swig_result_handler.cc", "swig/swig_table_iterator.cc", - "impl/exaudflib_main.cc", - "impl/msg_conversion.cc", "impl/msg_conversion.h", - "impl/check.cc", "impl/check.h", - "impl/socket_info.cc", "impl/socket_info.h", - "impl/socket_low_level.cc", "impl/socket_low_level.h", - "impl/global.cc", "impl/global.h", - "impl/socket_high_level.cc", "impl/socket_high_level.h", - "impl/swig/swig_factory.cc", - "impl/swig/swig_table_iterator.h", "impl/swig/swig_table_iterator.cc", - "impl/swig/swig_meta_data.h", "impl/swig/swig_meta_data.cc", - "impl/swig/swig_result_handler.h", "impl/swig/swig_result_handler.cc", - "impl/swig/swig_general_iterator.h", "impl/swig/swig_general_iterator.cc"], - defines = VM_ENABLED_DEFINES, - linkstatic = False, # Needs to be false, because otherwise we might get missing symbols when loading exaudflib_complete.so - deps = [":exaudflib-deps", ":zmqcontainer", "@zmq//:zmq", ":header", "//utils:utils"], -) diff --git a/exaudfclient/base/exaudflib/exascript.i b/exaudfclient/base/exaudflib/exascript.i deleted file mode 100644 index bc6abf9..0000000 --- a/exaudfclient/base/exaudflib/exascript.i +++ /dev/null @@ -1,136 +0,0 @@ -%begin %{ -#define SWIG_PYTHON_STRICT_BYTE_CHAR -%} - -%{ -#include "exaudflib/swig/swig_result_handler.h" -#include "exaudflib/swig/swig_meta_data.h" - -using namespace SWIGVMContainers; -#include "exaudflib/swig/script_data_transfer_objects_wrapper.h" -%} - -%ignore ExecutionGraph::ConnectionInformationWrapper::ConnectionInformationWrapper; -%include "exaudflib/script_data_transfer_objects_wrapper.h" -%newobject SWIGMetadata::connectionInformation(char*); -%newobject ConnectionInformationWrapper::copyKind(); -%newobject ConnectionInformationWrapper::copyAddress(); -%newobject ConnectionInformationWrapper::copyUser(); -%newobject ConnectionInformationWrapper::copyPassword(); - -%newobject ImportSpecificationWrapper::copySubselectColumnName(); -%newobject ImportSpecificationWrapper::copySubselectColumnType(); -%newobject ImportSpecificationWrapper::copyConnectionName(); -%newobject ImportSpecificationWrapper::copyKey(); -%newobject ImportSpecificationWrapper::copyValue(); - -%newobject ExportSpecificationWrapper::copyConnectionName(); -%newobject ExportSpecificationWrapper::copyKey(); -%newobject ExportSpecificationWrapper::copyValue(); -%newobject ExportSpecificationWrapper::copyCreatedBy(); -%newobject ExportSpecificationWrapper::copySourceColumnName(); - -%rename(Metadata) SWIGMetadata; -%rename(TableIterator) SWIGTableIterator; -%rename(ResultHandler) SWIGResultHandler; - -enum SWIGVM_datatype_e { - UNSUPPORTED = 0, - DOUBLE = 1, - INT32 = 2, - INT64 = 3, - NUMERIC = 4, - TIMESTAMP = 5, - DATE = 6, - STRING = 7, - BOOLEAN = 8 }; - -enum SWIGVM_itertype_e { - EXACTLY_ONCE = 1, - MULTIPLE = 2 -}; - -class SWIGMetadata { - public: - SWIGMetadata(); - - inline const char* databaseName(); - inline const char* databaseVersion(); - inline const char* scriptName(); - inline const char* scriptSchema(); - inline const char* currentUser(); - inline const char* scopeUser(); - inline const char* currentSchema(); - inline const char* scriptCode(); - inline const char* moduleContent(const char* name); - inline const ExecutionGraph::ConnectionInformationWrapper* connectionInformation(const char* connection_name); - inline const unsigned long long sessionID(); - inline const const char *sessionID_S(); - inline const unsigned long statementID(); - inline const unsigned int nodeCount(); - inline const unsigned int nodeID(); - inline const unsigned long long vmID(); - inline const const char *vmID_S(); - inline const unsigned long long memoryLimit(); - - inline unsigned int inputColumnCount(); - inline const char *inputColumnName(unsigned int col); - inline const SWIGVM_datatype_e inputColumnType(unsigned int col); - inline const char *inputColumnTypeName(unsigned int col); - inline const unsigned int inputColumnSize(unsigned int col); - inline const unsigned int inputColumnPrecision(unsigned int col); - inline const unsigned int inputColumnScale(unsigned int col); - inline const SWIGVM_itertype_e inputType(); - - inline unsigned int outputColumnCount(); - inline const char *outputColumnName(unsigned int col); - inline const SWIGVM_datatype_e outputColumnType(unsigned int col); - inline const char *outputColumnTypeName(unsigned int col); - inline const unsigned int outputColumnSize(unsigned int col); - inline const unsigned int outputColumnPrecision(unsigned int col); - inline const unsigned int outputColumnScale(unsigned int col); - inline const SWIGVM_itertype_e outputType(); - - inline const char* checkException(); - inline const char* pluginLanguageName(); -}; - -class SWIGTableIterator { - public: - SWIGTableIterator(); - inline const char* checkException(); - inline void reinitialize(); - inline bool next(); - inline bool eot(); - inline void reset(); - inline unsigned long restBufferSize(); - inline unsigned long rowsInGroup(); - inline unsigned long rowsCompleted(); - inline double getDouble(unsigned int col); - inline const char *getString(unsigned int col); - inline int getInt32(unsigned int col); - inline long long getInt64(unsigned int col); - inline const char *getNumeric(unsigned int col); - inline const char *getDate(unsigned int col); - inline const char *getTimestamp(unsigned int col); - inline bool getBoolean(unsigned int col); - inline bool wasNull(); -}; - -class SWIGResultHandler { - public: - SWIGResultHandler(SWIGTableIterator* it); - inline const char* checkException(); - inline void reinitialize(); - inline bool next(); - inline void flush(); - inline void setDouble(unsigned int col, double v); - inline void setString(unsigned int col, char *v, size_t l); - inline void setInt32(unsigned int col, int v); - inline void setInt64(unsigned int col, long long v); - inline void setNumeric(unsigned int col, char *v); - inline void setDate(unsigned int col, char *v); - inline void setTimestamp(unsigned int col, char *v); - inline void setBoolean(unsigned int col, bool v); - inline void setNull(unsigned int col); -}; diff --git a/exaudfclient/base/exaudflib/impl/check.cc b/exaudfclient/base/exaudflib/impl/check.cc deleted file mode 100644 index 14029d7..0000000 --- a/exaudfclient/base/exaudflib/impl/check.cc +++ /dev/null @@ -1,79 +0,0 @@ -#include "exaudflib/impl/check.h" -#include "exaudflib/impl/socket_info.h" -#include -#include -#include -#include - - -#include "utils/debug_message.h" - -namespace exaudflib { - namespace check { - static std::atomic_bool keep_checking(true); - static pthread_t check_thread; - static int first_ppid=-1; - static bool remote_client; - } -} - -void exaudflib::check::set_remote_client(bool value) { - remote_client = value; -} - -bool exaudflib::check::get_remote_client() { - return remote_client; -} - -void exaudflib::check::external_process_check() { - if (remote_client) return; - if (::access(socket_info::get_socket_file_name(), F_OK) != 0) { - ::sleep(1); // give me a chance to die with my parent process - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1000","exaudfclient aborting ... cannot access socket file " << socket_info::get_socket_url()+6 << "."); - DBG_STREAM_MSG(std::cerr,"### SWIGVM aborting with name '" << socket_info::get_socket_url() << "' (" << ::getppid() << ',' << ::getpid() << ')'); - ::abort(); - } -} - - -static void check_parent_pid(){ - int new_ppid=::getppid(); - if(exaudflib::check::first_ppid==-1){ // Initialize first_ppid - exaudflib::check::first_ppid=new_ppid; - } - // Check if ppid has changed, if client is in own namespace, - // the ppid will be forever 0 and never change. - // If the client runs as udfplugin the ppid will point to the exasql process - // and will change if it gets killed. Then client gets an orphaned process and - // will be adopted by another process - if(exaudflib::check::first_ppid!=new_ppid){ - ::sleep(1); // give me a chance to die with my parent process - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1001","exaudfclient aborting " << exaudflib::socket_info::get_socket_url() << " ... current parent pid " << new_ppid << " different to first parent pid " << exaudflib::check::first_ppid << "." ); - DBG_STREAM_MSG(std::cerr,"### SWIGVM aborting with name '" << exaudflib::socket_info::get_socket_url() << "' (" << ::getppid() << ',' << ::getpid() << ')'); - ::unlink(exaudflib::socket_info::get_socket_file_name()); - ::abort(); - } -} - -static void *check_thread_routine(void* data) -{ - while(exaudflib::check::keep_checking) { - exaudflib::check::external_process_check(); - check_parent_pid(); - ::usleep(100000); - } - return NULL; -} - -void exaudflib::check::start_check_thread() { - if (!remote_client) - pthread_create(&check_thread, NULL, check_thread_routine, NULL); -} - -void exaudflib::check::stop_check_thread() { - keep_checking = false; -} - -void exaudflib::check::cancel_check_thread() { - ::pthread_cancel(check_thread); -} diff --git a/exaudfclient/base/exaudflib/impl/check.h b/exaudfclient/base/exaudflib/impl/check.h deleted file mode 100644 index c856d4a..0000000 --- a/exaudfclient/base/exaudflib/impl/check.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef EXAUDFCLIENT_EXAUDFLIB_CHECK_H -#define EXAUDFCLIENT_EXAUDFLIB_CHECK_H - - -namespace exaudflib { - namespace check { - void external_process_check(); - void start_check_thread(); - void stop_check_thread(); - void cancel_check_thread(); - void set_remote_client(bool value); - bool get_remote_client(); - } -} - - -#endif //EXAUDFCLIENT_EXAUDFLIB_CHECK_H diff --git a/exaudfclient/base/exaudflib/impl/exaudflib_main.cc b/exaudfclient/base/exaudflib/impl/exaudflib_main.cc deleted file mode 100644 index f595f84..0000000 --- a/exaudfclient/base/exaudflib/impl/exaudflib_main.cc +++ /dev/null @@ -1,297 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "utils/debug_message.h" - -// swig lib -#include - - -#include "exaudflib/impl/check.h" -#include "exaudflib/impl/socket_info.h" -#include "exaudflib/impl/socket_low_level.h" -#include "exaudflib/impl/msg_conversion.h" -#include "exaudflib/impl/global.h" -#include "exaudflib/impl/socket_high_level.h" - -#include "exaudflib/vm/swig_vm.h" - - -#ifndef NDEBUG -#define SWIGVM_LOG_CLIENT -#endif -//#define SWIGVM_LOG_CLIENT -//#define LOG_COMMUNICATION - - -void print_args(int argc,char**argv){ - for (int i = 0; iexception_msg = ""; - vm->shutdown(); // Calls cleanup - if (vm->exception_msg.size()>0) { - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1110","### Caught error in vm->shutdown '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): " << vm->exception_msg); - msg ="F-UDF-CL-LIB-1111: Caught exception\n\n"+msg+"\n\n and caught another exception during cleanup\n\n"+vm->exception_msg; - } - } - delete_vm(vm); - } catch (SWIGVMContainers::SWIGVM::exception &err) { - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1112","### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): " << err.what()); - }catch(std::exception& err){ - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1113","### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): " << err.what()); - }catch(...){ - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1114","### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): "); - } - try{ - exaudflib::socket_high_level::send_close(socket, msg); - ::sleep(1); // give me a chance to die with my parent process - } catch (SWIGVMContainers::SWIGVM::exception &err) { - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1115","### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): " << err.what()); - }catch(std::exception& err){ - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1116","### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): " << err.what()); - }catch(...){ - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1117","### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << ")"); - } - - try{ - stop_all(socket); - } catch (SWIGVMContainers::SWIGVM::exception &err) { - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1118","### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): " << err.what()); - }catch(std::exception& err){ - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1119","### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): " << err.what()); - }catch(...){ - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1120","### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "):"); - } - return 1; -} - -extern "C" { - -int exaudfclient_main(std::functionvmMaker,int argc,char**argv) -{ - assert(exaudflib::global.SWIGVM_params_ref != nullptr); - -#ifdef UDF_PLUGIN_CLIENT - std::stringstream socket_name_ss; -#endif - std::string socket_name = argv[1]; - exaudflib::socket_info::set_socket_file_name(argv[1]); - exaudflib::socket_info::set_socket_url(argv[1]); - - exaudflib::check::set_remote_client(false); - - zmq::context_t context(1); - - DBG_COND_FUNC_CALL(std::cerr, print_args(argc,argv)); - - if (socket_name.length() < 5 ) { - PRINT_ERROR_MESSAGE(std::cerr,"F-UDF-CL-LIB-1122", "socket name '" << socket_name << "' is invalid." ); - abort(); - } - - if (socket_name.compare(0, 4, "tcp:") == 0) { - exaudflib::check::set_remote_client(true); - } - - if (socket_name.compare(0, 4, "ipc:") == 0) - { -#ifdef UDF_PLUGIN_CLIENT -/* - DO NOT REMOVE, required for Exasol 6.2 -*/ - //In case of protegrity the /tmp folder can't be used as it runs within the database (and not in an isolated container). - //There, the actual socket file path is defined in a environment variable. We need to replace it here. - if (socket_name.compare(0, 11, "ipc:///tmp/") == 0) { - socket_name_ss << "ipc://" << getenv("NSEXEC_TMP_PATH") << '/' << &(socket_name.c_str()[11]); - socket_name = socket_name_ss.str(); - exaudflib::socket_info::set_socket_file_name(::strdup(socket_name.c_str())); - } -#endif - exaudflib::socket_info::set_socket_file_name(&(exaudflib::socket_info::get_socket_file_name()[6])); - } - - DBG_STREAM_MSG(std::cerr,"### SWIGVM starting " << argv[0] << " with name '" << socket_name << - " (" << ::getppid() << ',' << ::getpid() << "): '" << argv[1] << '\''); - - exaudflib::check::start_check_thread(); - - - int linger_timeout = 0; - int recv_sock_timeout = 1000; - int send_sock_timeout = 1000; - - if (exaudflib::check::get_remote_client()) { - recv_sock_timeout = 10000; - send_sock_timeout = 5000; - } - -reinit: - - DBGMSG(std::cerr,"Reinit"); - zmq::socket_t socket(context, ZMQ_REQ); - - socket.setsockopt(ZMQ_LINGER, &linger_timeout, sizeof(linger_timeout)); - socket.setsockopt(ZMQ_RCVTIMEO, &recv_sock_timeout, sizeof(recv_sock_timeout)); - socket.setsockopt(ZMQ_SNDTIMEO, &send_sock_timeout, sizeof(send_sock_timeout)); - - if (exaudflib::check::get_remote_client()) socket.bind(socket_name.c_str()); - else socket.connect(socket_name.c_str()); - - exaudflib::global.sock = &socket; - exaudflib::global.SWIGVM_params_ref->exch = &exaudflib::global.exchandler; - - SWIGVMContainers::SWIGVM* vm=nullptr; - - if (!exaudflib::socket_high_level::send_init(socket, socket_name)) { - if (!exaudflib::check::get_remote_client() && exaudflib::global.exchandler.exthrowed) { - return handle_error(socket, socket_name, vm, "F-UDF-CL-LIB-1123: " + - exaudflib::global.exchandler.exmsg, false); - }else{ - goto reinit; - } - } - - exaudflib::global.initSwigParams(); - - bool shutdown_vm_in_case_of_error = false; - try { - vm = vmMaker(); - if (vm == nullptr) { - return handle_error(socket, socket_name, vm, "F-UDF-CL-LIB-1124: Unknown or unsupported VM type", false); - } - if (vm->exception_msg.size()>0) { - return handle_error(socket, socket_name, vm, "F-UDF-CL-LIB-1125: "+vm->exception_msg, false); - } - shutdown_vm_in_case_of_error = true; - exaudflib::socket_low_level::init(vm->useZmqSocketLocks()); - if (exaudflib::global.singleCallMode) { - ExecutionGraph::EmptyDTO noArg; // used as dummy arg - for (;;) { - // in single call mode, after MT_RUN from the client, - // EXASolution responds with a CALL message that specifies - // the single call function to be made - if (!exaudflib::socket_high_level::send_run(socket)) { - break; - } - - assert(exaudflib::global.singleCallFunction != SWIGVMContainers::single_call_function_id_e::SC_FN_NIL); - try { - const char* result = nullptr; - switch (exaudflib::global.singleCallFunction) - { - case SWIGVMContainers::single_call_function_id_e::SC_FN_NIL: - break; - case SWIGVMContainers::single_call_function_id_e::SC_FN_DEFAULT_OUTPUT_COLUMNS: - result = vm->singleCall(exaudflib::global.singleCallFunction,noArg); - break; - case SWIGVMContainers::single_call_function_id_e::SC_FN_GENERATE_SQL_FOR_IMPORT_SPEC: - assert(!exaudflib::global.singleCall_ImportSpecificationArg.isEmpty()); - result = vm->singleCall(exaudflib::global.singleCallFunction,exaudflib::global.singleCall_ImportSpecificationArg); - exaudflib::global.singleCall_ImportSpecificationArg = ExecutionGraph::ImportSpecification(); // delete the last argument - break; - case SWIGVMContainers::single_call_function_id_e::SC_FN_GENERATE_SQL_FOR_EXPORT_SPEC: - assert(!exaudflib::global.singleCall_ExportSpecificationArg.isEmpty()); - result = vm->singleCall(exaudflib::global.singleCallFunction,exaudflib::global.singleCall_ExportSpecificationArg); - exaudflib::global.singleCall_ExportSpecificationArg = ExecutionGraph::ExportSpecification(); // delete the last argument - break; - case SWIGVMContainers::single_call_function_id_e::SC_FN_VIRTUAL_SCHEMA_ADAPTER_CALL: - assert(!exaudflib::global.singleCall_StringArg.isEmpty()); - result = vm->singleCall(exaudflib::global.singleCallFunction,exaudflib::global.singleCall_StringArg); - break; - } - if (vm->exception_msg.size()>0) { - return handle_error(socket, socket_name, vm, "F-UDF-CL-LIB-1126: "+vm->exception_msg,true); - } - - if (vm->calledUndefinedSingleCall.size()>0) { - exaudflib::socket_high_level::send_undefined_call(socket, vm->calledUndefinedSingleCall); - } else { - exaudflib::socket_high_level::send_return(socket,result); - } - - if (!exaudflib::socket_high_level::send_done(socket)) { - break; - } - } catch(...) {} - } - } else { - for(;;) { - if (!exaudflib::socket_high_level::send_run(socket)) - break; - exaudflib::global.SWIGVM_params_ref->inp_force_finish = false; - while(!vm->run_()) - { - if (vm->exception_msg.size()>0) { - return handle_error(socket, socket_name, vm, "F-UDF-CL-LIB-1127: "+vm->exception_msg,true); - } - } - if (!exaudflib::socket_high_level::send_done(socket)) - break; - } - } - - if (vm != nullptr) - { - vm->shutdown(); - if (vm->exception_msg.size()>0) { - return handle_error(socket, socket_name, vm, "F-UDF-CL-LIB-1128: "+vm->exception_msg,false); - } - } - exaudflib::socket_high_level::send_finished(socket); - } catch (SWIGVMContainers::SWIGVM::exception &err) { - DBG_STREAM_MSG(std::cerr,"### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): " << err.what()); - return handle_error(socket, socket_name, vm, "F-UDF-CL-LIB-1129: "+std::string(err.what()),shutdown_vm_in_case_of_error); - } catch (std::exception &err) { - DBG_STREAM_MSG(std::cerr,"### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << "): " << err.what()); - return handle_error(socket, socket_name, vm, "F-UDF-CL-LIB-1130: "+std::string(err.what()),shutdown_vm_in_case_of_error); - } catch (...) { - DBG_STREAM_MSG(std::cerr,"### SWIGVM crashing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << ')'); - return handle_error(socket, socket_name, vm, "F-UDF-CL-LIB-1131: Internal/Unknown error",shutdown_vm_in_case_of_error); - } - - DBG_STREAM_MSG(std::cerr,"### SWIGVM finishing with name '" << socket_name << " (" << ::getppid() << ',' << ::getpid() << ')'); - - delete_vm(vm); - stop_all(socket); - return 0; -} - - -} // extern "C" diff --git a/exaudfclient/base/exaudflib/impl/global.cc b/exaudfclient/base/exaudflib/impl/global.cc deleted file mode 100644 index d5f570b..0000000 --- a/exaudfclient/base/exaudflib/impl/global.cc +++ /dev/null @@ -1,73 +0,0 @@ -#include "exaudflib/impl/global.h" -#include - -namespace exaudflib { -static std::string g_database_name; -static std::string g_database_version; -static std::string g_script_name; -static std::string g_script_schema; -static std::string g_current_user; -static std::string g_scope_user; -static std::string g_current_schema; -static std::string g_source_code; -static unsigned long long g_session_id; -static unsigned long g_statement_id; -static unsigned int g_node_count; -static unsigned int g_node_id; -static unsigned long long g_vm_id; - -Global global; -} - -exaudflib::Global::Global() -: SWIGVM_params_ref(nullptr), sock(nullptr) {} - -void exaudflib::Global::initSwigParams() { - /** - * We need to store the strings here in static variables as the pointers are shared between the linker namespaces. - * It made trouble allocating the strings on the heap in the past: it might occur that the destructor is - * called twice. As a workaround we keep it as static variables which are deallocated only at the final termination - * of the program: It still might occur that the destructor is called more than once, but at least everything else has - * already finished. - */ - SWIGVM_params_ref->dbname = (char*) g_database_name.c_str(); - SWIGVM_params_ref->dbversion = (char*) g_database_version.c_str(); - SWIGVM_params_ref->script_name = (char*) g_script_name.c_str(); - SWIGVM_params_ref->script_schema = (char*) g_script_schema.c_str(); - SWIGVM_params_ref->current_user = (char*) g_current_user.c_str(); - SWIGVM_params_ref->current_schema = (char*) g_current_schema.c_str(); - SWIGVM_params_ref->scope_user = (char*) g_scope_user.c_str(); - SWIGVM_params_ref->script_code = (char*) g_source_code.c_str(); - SWIGVM_params_ref->session_id = g_session_id; - SWIGVM_params_ref->statement_id = g_statement_id; - SWIGVM_params_ref->node_count = g_node_count; - SWIGVM_params_ref->node_id = g_node_id; - SWIGVM_params_ref->vm_id = g_vm_id; - SWIGVM_params_ref->singleCallMode = singleCallMode; -} - -void exaudflib::Global::writeScriptParams(const exascript_info &rep) { - g_database_name = rep.database_name(); - g_database_version = rep.database_version(); - g_script_name = rep.script_name(); - g_script_schema = rep.script_schema(); - g_current_user = rep.current_user(); - g_scope_user = rep.scope_user(); - if (g_scope_user.size()==0) { // for backward compatibility when testing with EXASOL 6.0.8 installations at OTTO Brain - g_scope_user=g_current_user; - } - g_current_schema = rep.current_schema(); - g_source_code = rep.source_code(); - g_session_id = rep.session_id(); - g_statement_id = rep.statement_id(); - g_node_count = rep.node_count(); - g_node_id = rep.node_id(); - g_vm_id = rep.vm_id(); -} - -extern "C" { - void set_SWIGVM_params(SWIGVMContainers::SWIGVM_params_t* p) { - exaudflib::global.SWIGVM_params_ref = p; - } -} - diff --git a/exaudfclient/base/exaudflib/impl/global.h b/exaudfclient/base/exaudflib/impl/global.h deleted file mode 100644 index 61e0b8c..0000000 --- a/exaudfclient/base/exaudflib/impl/global.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef EXAUDFCLIENT_EXUDFLIB_GLOBAL_H -#define EXAUDFCLIENT_EXUDFLIB_GLOBAL_H - -#include "exaudflib/swig/script_data_transfer_objects.h" -#include "exaudflib/zmqcontainer.pb.h" -#include "exaudflib/swig/swig_common.h" -#include - -namespace exaudflib { - struct Global { - Global(); - void initSwigParams(); - void writeScriptParams(const exascript_info &rep); - SWIGVMContainers::SWIGVM_params_t * SWIGVM_params_ref; - zmq::socket_t *sock; - ExecutionGraph::StringDTO singleCall_StringArg; - bool singleCallMode; - SWIGVMContainers::single_call_function_id_e singleCallFunction; - ExecutionGraph::ImportSpecification singleCall_ImportSpecificationArg; - ExecutionGraph::ExportSpecification singleCall_ExportSpecificationArg; - SWIGVMContainers::SWIGVMExceptionHandler exchandler; - }; - - extern Global global; -} - - -#endif //EXAUDFCLIENT_EXUDFLIB_GLOBAL_H diff --git a/exaudfclient/base/exaudflib/impl/msg_conversion.cc b/exaudfclient/base/exaudflib/impl/msg_conversion.cc deleted file mode 100644 index c09ee02..0000000 --- a/exaudfclient/base/exaudflib/impl/msg_conversion.cc +++ /dev/null @@ -1,71 +0,0 @@ -#include "exaudflib/impl/msg_conversion.h" - -std::string exaudflib::msg_conversion::convert_message_type_to_string(int message_type){ - switch (message_type) - { - case 0: - return "MT_UNKNOWN"; - case 1: - return "MT_CLIENT"; - case 2: - return "MT_INFO"; - case 3: - return "MT_META"; - case 4: - return "MT_CLOSE"; - case 5: - return "MT_IMPORT"; - case 6: - return "MT_NEXT"; - case 7: - return "MT_RESET"; - case 8: - return "MT_EMIT"; - case 9: - return "MT_RUN"; - case 10: - return "MT_DONE"; - case 11: - return "MT_CLEANUP"; - case 12: - return "MT_FINISHED"; - case 13: - return "MT_PING_PONG"; - case 14: - return "MT_TRY_AGAIN"; - case 15: - return "MT_CALL"; - case 16: - return "MT_RETURN"; - case 17: - return "MT_UNDEFINED_CALL"; - default: - return "unknown: " + message_type; - } -} - -std::string exaudflib::msg_conversion::convert_type_to_string(int type){ - switch (type) - { - case 0: - return "PB_UNSUPPORTED"; - case 1: - return "PB_DOUBLE"; - case 2: - return "PB_INT32"; - case 3: - return "PB_INT64"; - case 4: - return "PB_NUMERIC"; - case 5: - return "PB_TIMESTAMP"; - case 6: - return "PB_DATE"; - case 7: - return "PB_STRING"; - case 8: - return "PB_BOOLEAN"; - default: - return "unknown: " + type; - } -} diff --git a/exaudfclient/base/exaudflib/impl/msg_conversion.h b/exaudfclient/base/exaudflib/impl/msg_conversion.h deleted file mode 100644 index fbeec4d..0000000 --- a/exaudfclient/base/exaudflib/impl/msg_conversion.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef EXAUDFCLIENT_EXAUDFLIB_MSG_CONVERSION_H -#define EXAUDFCLIENT_EXAUDFLIB_MSG_CONVERSION_H - -#include - -namespace exaudflib { - namespace msg_conversion { - std::string convert_message_type_to_string(int message_type); - std::string convert_type_to_string(int type); - } -} - - -#endif //EXAUDFCLIENT_EXAUDFLIB_MSG_CONVERSION_H diff --git a/exaudfclient/base/exaudflib/impl/socket_high_level.cc b/exaudfclient/base/exaudflib/impl/socket_high_level.cc deleted file mode 100644 index 13048b6..0000000 --- a/exaudfclient/base/exaudflib/impl/socket_high_level.cc +++ /dev/null @@ -1,528 +0,0 @@ -#include "exaudflib/impl/socket_high_level.h" - -#include "exaudflib/impl/socket_low_level.h" -#include "exaudflib/zmqcontainer.pb.h" -#include "exaudflib/impl/msg_conversion.h" -#include "exaudflib/impl/global.h" -#include "exaudflib/swig/swig_common.h" -#include "exaudflib/vm/swig_vm.h" -#include -#include "utils/debug_message.h" - -namespace exaudflib { - namespace socket_high_level { - //static exascript_vmtype vm_type; - static exascript_request request; - static exascript_response response; - static std::string output_buffer; - } -} - - -bool exaudflib::socket_high_level::send_init(zmq::socket_t &socket, const std::string client_name) -{ - exaudflib::socket_high_level::request.Clear(); - exaudflib::socket_high_level::request.set_type(MT_CLIENT); - exaudflib::socket_high_level::request.set_connection_id(0); - exascript_client *req = exaudflib::socket_high_level::request.mutable_client(); - req->set_client_name(client_name); - if (!exaudflib::socket_high_level::request.SerializeToString(&exaudflib::socket_high_level::output_buffer)) { - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1002: Communication error: failed to serialize data"); - return false; - } - zmq::message_t zmsg((void*)exaudflib::socket_high_level::output_buffer.c_str(), - exaudflib::socket_high_level::output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(socket, zmsg); - - zmq::message_t zmsgrecv; - exaudflib::socket_high_level::response.Clear(); - if (!exaudflib::socket_low_level::socket_recv(socket, zmsgrecv, true)) - return false; - if (!exaudflib::socket_high_level::response.ParseFromArray(zmsgrecv.data(), zmsgrecv.size())) { - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1003: Failed to parse data"); - return false; - } - - exaudflib::global.SWIGVM_params_ref->connection_id = exaudflib::socket_high_level::response.connection_id(); - DBG_STREAM_MSG(std::cerr,"### SWIGVM connected with id " << - std::hex << exaudflib::global.SWIGVM_params_ref->connection_id); - if (exaudflib::socket_high_level::response.type() == MT_CLOSE) { - if (exaudflib::socket_high_level::response.close().has_exception_message()) - exaudflib::global.exchandler.setException( - exaudflib::socket_high_level::response.close().exception_message().c_str()); - else exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1004: Connection closed by server"); - return false; - } - if (exaudflib::socket_high_level::response.type() != MT_INFO) { - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1005: Wrong message type, should be MT_INFO got "+ - exaudflib::msg_conversion::convert_message_type_to_string(exaudflib::socket_high_level::response.type())); - return false; - } - const exascript_info &rep = exaudflib::socket_high_level::response.info(); - exaudflib::global.writeScriptParams(rep); - //vm_type = rep.vm_type(); - - - exaudflib::global.SWIGVM_params_ref->maximal_memory_limit = rep.maximal_memory_limit(); - struct rlimit d; - d.rlim_cur = d.rlim_max = rep.maximal_memory_limit(); - if (setrlimit(RLIMIT_RSS, &d) != 0) -#ifdef SWIGVM_LOG_CLIENT - std::cerr << "W-UDF-CL-LIB-1006: Failed to set memory limit" << std::endl; -#else - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1007: Failed to set memory limit"); -#endif - d.rlim_cur = d.rlim_max = 0; // 0 for no core dumps, RLIM_INFINITY to enable coredumps of any size - if (setrlimit(RLIMIT_CORE, &d) != 0) -#ifdef SWIGVM_LOG_CLIENT - std::cerr << "W-UDF-CL-LIB-1008: Failed to set core dump size limit" << std::endl; -#else - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1009: Failed to set core dump size limit"); -#endif - /* d.rlim_cur = d.rlim_max = 65536; */ - getrlimit(RLIMIT_NOFILE,&d); - if (d.rlim_max < 32768) - { - //#ifdef SWIGVM_LOG_CLIENT - std::cerr << "W-UDF-CL-LIB-1010: Reducing RLIMIT_NOFILE below 32768" << std::endl; - //#endif - } - d.rlim_cur = d.rlim_max = std::min(32768,(int)d.rlim_max); - if (setrlimit(RLIMIT_NOFILE, &d) != 0) -#ifdef SWIGVM_LOG_CLIENT - std::cerr << "W-UDF-CL-LIB-1011: Failed to set nofile limit" << std::endl; -#else - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1012: Failed to set nofile limit"); -#endif - d.rlim_cur = d.rlim_max = 32768; - if (setrlimit(RLIMIT_NPROC, &d) != 0) - { - std::cerr << "W-UDF-CL-LIB-1013: Failed to set nproc limit to 32k trying 8k ..." << std::endl; - d.rlim_cur = d.rlim_max = 8192; - if (setrlimit(RLIMIT_NPROC, &d) != 0) -#ifdef SWIGVM_LOG_CLIENT - std::cerr << "W-UDF-CL-LIB-1014: Failed to set nproc limit" << std::endl; -#else - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1015: Failed to set nproc limit"); -#endif - } - - { /* send meta request */ - exaudflib::socket_high_level::request.Clear(); - exaudflib::socket_high_level::request.set_type(MT_META); - exaudflib::socket_high_level::request.set_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id); - if (!exaudflib::socket_high_level::request.SerializeToString(&exaudflib::socket_high_level::output_buffer)) { - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1016: Communication error: failed to serialize data"); - return false; - } - zmq::message_t zmsg((void*)exaudflib::socket_high_level::output_buffer.c_str(), - exaudflib::socket_high_level::output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(socket, zmsg); - } /* receive meta response */ - { zmq::message_t zmsg; - exaudflib::socket_low_level::socket_recv(socket, zmsg); - exaudflib::socket_high_level::response.Clear(); - if (!exaudflib::socket_high_level::response.ParseFromArray(zmsg.data(), zmsg.size())) { - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1017: Communication error: failed to parse data"); - return false; - } - if (exaudflib::socket_high_level::response.type() == MT_CLOSE) { - if (exaudflib::socket_high_level::response.close().has_exception_message()) - exaudflib::global.exchandler.setException( - exaudflib::socket_high_level::response.close().exception_message().c_str()); - else exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1018: Connection closed by server"); - return false; - } - if (exaudflib::socket_high_level::response.type() != MT_META) { - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1019: Wrong message type, should be META, got "+ - exaudflib::msg_conversion::convert_message_type_to_string(exaudflib::socket_high_level::response.type())); - return false; - } - const exascript_metadata &rep = exaudflib::socket_high_level::response.meta(); - exaudflib::global.singleCallMode = rep.single_call_mode(); - exaudflib::global.SWIGVM_params_ref->inp_iter_type = (SWIGVMContainers::SWIGVM_itertype_e)(rep.input_iter_type()); - exaudflib::global.SWIGVM_params_ref->out_iter_type = (SWIGVMContainers::SWIGVM_itertype_e)(rep.output_iter_type()); - for (int col = 0; col < rep.input_columns_size(); ++col) { - const exascript_metadata_column_definition &coldef = rep.input_columns(col); - exaudflib::global.SWIGVM_params_ref->inp_names->push_back(coldef.name()); - exaudflib::global.SWIGVM_params_ref->inp_types->push_back(SWIGVMContainers::SWIGVM_columntype_t()); - SWIGVMContainers::SWIGVM_columntype_t &coltype = exaudflib::global.SWIGVM_params_ref->inp_types->back(); - coltype.len = 0; coltype.prec = 0; coltype.scale = 0; - coltype.type_name = coldef.type_name(); - switch (coldef.type()) { - case PB_UNSUPPORTED: - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1020: Unsupported input column type found"); - return false; - case PB_DOUBLE: - coltype.type = SWIGVMContainers::DOUBLE; - break; - case PB_INT32: - coltype.type = SWIGVMContainers::INT32; - coltype.prec = coldef.precision(); - coltype.scale = coldef.scale(); - break; - case PB_INT64: - coltype.type = SWIGVMContainers::INT64; - coltype.prec = coldef.precision(); - coltype.scale = coldef.scale(); - break; - case PB_NUMERIC: - coltype.type = SWIGVMContainers::NUMERIC; - coltype.prec = coldef.precision(); - coltype.scale = coldef.scale(); - break; - case PB_TIMESTAMP: - coltype.type = SWIGVMContainers::TIMESTAMP; - break; - case PB_DATE: - coltype.type = SWIGVMContainers::DATE; - break; - case PB_STRING: - coltype.type = SWIGVMContainers::STRING; - coltype.len = coldef.size(); - break; - case PB_BOOLEAN: - coltype.type = SWIGVMContainers::BOOLEAN; - break; - default: - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1021: Unknown input column type found, got "+coldef.type()); - return false; - } - } - for (int col = 0; col < rep.output_columns_size(); ++col) { - const exascript_metadata_column_definition &coldef = rep.output_columns(col); - exaudflib::global.SWIGVM_params_ref->out_names->push_back(coldef.name()); - exaudflib::global.SWIGVM_params_ref->out_types->push_back(SWIGVMContainers::SWIGVM_columntype_t()); - SWIGVMContainers::SWIGVM_columntype_t &coltype = exaudflib::global.SWIGVM_params_ref->out_types->back(); - coltype.len = 0; coltype.prec = 0; coltype.scale = 0; - coltype.type_name = coldef.type_name(); - switch (coldef.type()) { - case PB_UNSUPPORTED: - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1022: Unsupported output column type found"); - return false; - case PB_DOUBLE: - coltype.type = SWIGVMContainers::DOUBLE; - break; - case PB_INT32: - coltype.type = SWIGVMContainers::INT32; - coltype.prec = coldef.precision(); - coltype.scale = coldef.scale(); - break; - case PB_INT64: - coltype.type = SWIGVMContainers::INT64; - coltype.prec = coldef.precision(); - coltype.scale = coldef.scale(); - break; - case PB_NUMERIC: - coltype.type = SWIGVMContainers::NUMERIC; - coltype.prec = coldef.precision(); - coltype.scale = coldef.scale(); - break; - case PB_TIMESTAMP: - coltype.type = SWIGVMContainers::TIMESTAMP; - break; - case PB_DATE: - coltype.type = SWIGVMContainers::DATE; - break; - case PB_STRING: - coltype.type = SWIGVMContainers::STRING; - coltype.len = coldef.size(); - break; - case PB_BOOLEAN: - coltype.type = SWIGVMContainers::BOOLEAN; - break; - default: - exaudflib::global.exchandler.setException("F-UDF-CL-LIB-1023: Unknown output column type found, got "+coldef.type()); - return false; - } - } - } - return true; -} - -void exaudflib::socket_high_level::send_close(zmq::socket_t &socket, const std::string &exmsg) -{ - exaudflib::socket_high_level::request.Clear(); - exaudflib::socket_high_level::request.set_type(MT_CLOSE); - exaudflib::socket_high_level::request.set_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id); - exascript_close *req = - exaudflib::socket_high_level::request.mutable_close(); - if (exmsg != "") req->set_exception_message(exmsg); - exaudflib::socket_high_level::request.SerializeToString(&exaudflib::socket_high_level::output_buffer); - zmq::message_t zmsg((void*)exaudflib::socket_high_level::output_buffer.c_str(), - exaudflib::socket_high_level::output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(socket, zmsg); - - { /* receive finished response, so we know that the DB knows that we are going to close and - all potential exceptions have been received on DB side */ - zmq::message_t zmsg; - exaudflib::socket_low_level::socket_recv(socket, zmsg); - exaudflib::socket_high_level::response.Clear(); - if(!exaudflib::socket_high_level::response.ParseFromArray(zmsg.data(), zmsg.size())) { - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1024: Communication error: failed to parse data"); - } - else if (exaudflib::socket_high_level::response.type() != MT_FINISHED) { - throw - SWIGVMContainers::SWIGVM::exception( - "F-UDF-CL-LIB-1025: Wrong response type, should be MT_FINISHED, got "+ - exaudflib::msg_conversion::convert_message_type_to_string( - exaudflib::socket_high_level::response.type())); - } - } -} - -bool exaudflib::socket_high_level::send_run(zmq::socket_t &socket) -{ - { - /* send done request */ - exaudflib::socket_high_level::request.Clear(); - exaudflib::socket_high_level::request.set_type(MT_RUN); - exaudflib::socket_high_level::request.set_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id); - if (!exaudflib::socket_high_level::request.SerializeToString(&exaudflib::socket_high_level::output_buffer)) - { - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1026: Communication error: failed to serialize data"); - } - zmq::message_t zmsg((void*)exaudflib::socket_high_level::output_buffer.c_str(), - exaudflib::socket_high_level::output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(socket, zmsg); - } { /* receive done response */ - zmq::message_t zmsg; - exaudflib::socket_low_level::socket_recv(socket, zmsg); - exaudflib::socket_high_level::response.Clear(); - if (!exaudflib::socket_high_level::response.ParseFromArray(zmsg.data(), zmsg.size())) - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1027: Communication error: failed to parse data"); - if (exaudflib::socket_high_level::response.type() == MT_CLOSE) { - if (exaudflib::socket_high_level::response.close().has_exception_message()) - throw SWIGVMContainers::SWIGVM::exception( - exaudflib::socket_high_level::response.close().exception_message().c_str()); - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1028: Wrong response type, got empty MT_CLOSE"); - } else if (exaudflib::socket_high_level::response.type() == MT_CLEANUP) { - return false; - } else if (exaudflib::global.singleCallMode && exaudflib::socket_high_level::response.type() == MT_CALL) { - assert(exaudflib::global.singleCallMode); - exascript_single_call_rep sc = exaudflib::socket_high_level::response.call(); - exaudflib::global.singleCallFunction = static_cast(sc.fn()); - - switch (exaudflib::global.singleCallFunction) - { - case SWIGVMContainers::single_call_function_id_e::SC_FN_NIL: - case SWIGVMContainers::single_call_function_id_e::SC_FN_DEFAULT_OUTPUT_COLUMNS: - break; - case SWIGVMContainers::single_call_function_id_e::SC_FN_GENERATE_SQL_FOR_IMPORT_SPEC: - { - - if (!sc.has_import_specification()) - { - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1029: internal error SC_FN_GENERATE_SQL_FOR_IMPORT_SPEC without import specification"); - } - const import_specification_rep& is_proto = sc.import_specification(); - exaudflib::global.singleCall_ImportSpecificationArg = ExecutionGraph::ImportSpecification(is_proto.is_subselect()); - if (is_proto.has_connection_information()) - { - const connection_information_rep& ci_proto = is_proto.connection_information(); - ExecutionGraph::ConnectionInformation connection_info(ci_proto.kind(), ci_proto.address(), ci_proto.user(), ci_proto.password()); - exaudflib::global.singleCall_ImportSpecificationArg.setConnectionInformation(connection_info); - } - if (is_proto.has_connection_name()) - { - exaudflib::global.singleCall_ImportSpecificationArg.setConnectionName(is_proto.connection_name()); - } - for (int i=0; iset_result(result); - exaudflib::socket_high_level::request.set_allocated_call_result(rr); - exaudflib::socket_high_level::request.set_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id); - if (!exaudflib::socket_high_level::request.SerializeToString(&exaudflib::socket_high_level::output_buffer)) - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1033: Communication error: failed to serialize data"); - zmq::message_t zmsg((void*)exaudflib::socket_high_level::output_buffer.c_str(), - exaudflib::socket_high_level::output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(socket, zmsg); - } { /* receive return response */ - zmq::message_t zmsg; - exaudflib::socket_low_level::socket_recv(socket, zmsg); - exaudflib::socket_high_level::response.Clear(); - if (!exaudflib::socket_high_level::response.ParseFromArray(zmsg.data(), zmsg.size())) - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1034: Communication error: failed to parse data"); - if (exaudflib::socket_high_level::response.type() == MT_CLOSE) { - if (exaudflib::socket_high_level::response.close().has_exception_message()) - throw SWIGVMContainers::SWIGVM::exception( - exaudflib::socket_high_level::response.close().exception_message().c_str()); - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1035: Wrong response type, got empty close response"); - } else if (exaudflib::socket_high_level::response.type() == MT_CLEANUP) { - return false; - } else if (exaudflib::socket_high_level::response.type() != MT_RETURN) { - throw SWIGVMContainers::SWIGVM::exception( - "F-UDF-CL-LIB-1036: Wrong response type, should be MT_RETURN, got "+ - exaudflib::msg_conversion::convert_message_type_to_string( - exaudflib::socket_high_level::response.type())); - } - } - return true; -} - -void exaudflib::socket_high_level::send_undefined_call(zmq::socket_t &socket, const std::string& fn) -{ - { /* send return request */ - exaudflib::socket_high_level::request.Clear(); - exaudflib::socket_high_level::request.set_type(MT_UNDEFINED_CALL); - ::exascript_undefined_call_req* uc = new ::exascript_undefined_call_req(); - uc->set_remote_fn(fn); - exaudflib::socket_high_level::request.set_allocated_undefined_call(uc); - exaudflib::socket_high_level::request.set_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id); - if (!exaudflib::socket_high_level::request.SerializeToString(&exaudflib::socket_high_level::output_buffer)) - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1037: Communication error: failed to serialize data"); - zmq::message_t zmsg((void*)exaudflib::socket_high_level::output_buffer.c_str(), - exaudflib::socket_high_level::output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(socket, zmsg); - } { /* receive return response */ - zmq::message_t zmsg; - exaudflib::socket_low_level::socket_recv(socket, zmsg); - exaudflib::socket_high_level::response.Clear(); - if (!exaudflib::socket_high_level::response.ParseFromArray(zmsg.data(), zmsg.size())) - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1038: Communication error: failed to parse data"); - if (exaudflib::socket_high_level::response.type() != MT_UNDEFINED_CALL) { - throw SWIGVMContainers::SWIGVM::exception( - "F-UDF-CL-LIB-1039: Wrong response type, should be MT_UNDEFINED_CALL, got "+ - exaudflib::msg_conversion::convert_message_type_to_string( - exaudflib::socket_high_level::response.type())); - } - } -} - -bool exaudflib::socket_high_level::send_done(zmq::socket_t &socket) -{ - { /* send done request */ - exaudflib::socket_high_level::request.Clear(); - exaudflib::socket_high_level::request.set_type(MT_DONE); - exaudflib::socket_high_level::request.set_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id); - if (!exaudflib::socket_high_level::request.SerializeToString(&exaudflib::socket_high_level::output_buffer)) - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1040: Communication error: failed to serialize data"); - zmq::message_t zmsg((void*)exaudflib::socket_high_level::output_buffer.c_str(), - exaudflib::socket_high_level::output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(socket, zmsg); - } - { /* receive done response */ - zmq::message_t zmsg; - exaudflib::socket_low_level::socket_recv(socket, zmsg); - exaudflib::socket_high_level::response.Clear(); - if (!exaudflib::socket_high_level::response.ParseFromArray(zmsg.data(), zmsg.size())) - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1041: Communication error: failed to parse data"); - if (exaudflib::socket_high_level::response.type() == MT_CLOSE) { - if (exaudflib::socket_high_level::response.close().has_exception_message()) - throw SWIGVMContainers::SWIGVM::exception( - exaudflib::socket_high_level::response.close().exception_message().c_str()); - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1042: Wrong response type, got empty close response"); - } else if (exaudflib::socket_high_level::response.type() == MT_CLEANUP) { - return false; - } else if (exaudflib::socket_high_level::response.type() != MT_DONE) - throw SWIGVMContainers::SWIGVM::exception( - "F-UDF-CL-LIB-1043: Wrong response type, should be MT_DONE, got "+ - exaudflib::msg_conversion::convert_message_type_to_string( - exaudflib::socket_high_level::response.type())); - } - return true; -} - -void exaudflib::socket_high_level::send_finished(zmq::socket_t &socket) -{ - { /* send done request */ - exaudflib::socket_high_level::request.Clear(); - exaudflib::socket_high_level::request.set_type(MT_FINISHED); - exaudflib::socket_high_level::request.set_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id); - if (!exaudflib::socket_high_level::request.SerializeToString(&exaudflib::socket_high_level::output_buffer)) - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1044: Communication error: failed to serialize data"); - zmq::message_t zmsg((void*)exaudflib::socket_high_level::output_buffer.c_str(), - exaudflib::socket_high_level::output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(socket, zmsg); - } { /* receive done response */ - zmq::message_t zmsg; - exaudflib::socket_low_level::socket_recv(socket, zmsg); - exaudflib::socket_high_level::response.Clear(); - if(!exaudflib::socket_high_level::response.ParseFromArray(zmsg.data(), zmsg.size())) - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1045: Communication error: failed to parse data"); - if (exaudflib::socket_high_level::response.type() == MT_CLOSE) { - if (exaudflib::socket_high_level::response.close().has_exception_message()) - throw SWIGVMContainers::SWIGVM::exception(exaudflib::socket_high_level::response.close().exception_message().c_str()); - throw SWIGVMContainers::SWIGVM::exception("F-UDF-CL-LIB-1046: Wrong response type, got empty MT_CLOSE"); - } else if (exaudflib::socket_high_level::response.type() != MT_FINISHED) - throw SWIGVMContainers::SWIGVM::exception( - "F-UDF-CL-LIB-1047: Wrong response type, should be MT_FINISHED, got"+ - exaudflib::msg_conversion::convert_message_type_to_string( - exaudflib::socket_high_level::response.type())); - } -} diff --git a/exaudfclient/base/exaudflib/impl/socket_high_level.h b/exaudfclient/base/exaudflib/impl/socket_high_level.h deleted file mode 100644 index 5180cc1..0000000 --- a/exaudfclient/base/exaudflib/impl/socket_high_level.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef EXAUDFLIB_SOCKET_HIGH_LEVEL_H -#define EXAUDFLIB_SOCKET_HIGH_LEVEL_H - -#include -#include - -namespace exaudflib { - namespace socket_high_level { - - bool send_init(zmq::socket_t &socket, const std::string client_name); - void send_close(zmq::socket_t &socket, const std::string &exmsg); - bool send_run(zmq::socket_t &socket); - void send_undefined_call(zmq::socket_t &socket, const std::string& fn); - bool send_done(zmq::socket_t &socket); - void send_finished(zmq::socket_t &socket); - bool send_return(zmq::socket_t &socket, const char* result); - - } //socket_high_level -} //exaudflib - - -#endif //EXAUDFLIB_SOCKET_HIGH_LEVEL_H diff --git a/exaudfclient/base/exaudflib/impl/socket_info.cc b/exaudfclient/base/exaudflib/impl/socket_info.cc deleted file mode 100644 index 9df03c2..0000000 --- a/exaudfclient/base/exaudflib/impl/socket_info.cc +++ /dev/null @@ -1,26 +0,0 @@ -#include "exaudflib/impl/socket_info.h" - - -namespace exaudflib { - namespace socket_info { - static const char *socket_file_name; - static const char *socket_name_url; - } -} - - -void exaudflib::socket_info::set_socket_url(const char* the_socket_url) { - socket_name_url = the_socket_url; -} - -const char* exaudflib::socket_info::get_socket_url() { - return socket_name_url; -} - -void exaudflib::socket_info::set_socket_file_name(const char* the_socket_file_name) { - socket_file_name = the_socket_file_name; -} - -const char* exaudflib::socket_info::get_socket_file_name() { - return socket_file_name; -} diff --git a/exaudfclient/base/exaudflib/impl/socket_info.h b/exaudfclient/base/exaudflib/impl/socket_info.h deleted file mode 100644 index 15de4c1..0000000 --- a/exaudfclient/base/exaudflib/impl/socket_info.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef EXAUDFCLIENT_SOCKET_INFO_H -#define EXAUDFCLIENT_SOCKET_INFO_H - -namespace exaudflib { - namespace socket_info { - void set_socket_url(const char*); - void set_socket_file_name(const char*); - const char* get_socket_file_name(); - const char* get_socket_url(); - } -} - - -#endif //EXAUDFCLIENT_SOCKET_INFO_H diff --git a/exaudfclient/base/exaudflib/impl/socket_low_level.cc b/exaudfclient/base/exaudflib/impl/socket_low_level.cc deleted file mode 100644 index 9a324d0..0000000 --- a/exaudfclient/base/exaudflib/impl/socket_low_level.cc +++ /dev/null @@ -1,101 +0,0 @@ -#include "exaudflib/impl/socket_low_level.h" -#include "exaudflib/impl/check.h" -#include "utils/debug_message.h" -#include -#include -#include - -namespace exaudflib { - namespace socket_low_level { - static std::mutex zmq_socket_mutex; - static bool use_zmq_socket_locks = false; - } -} - -void exaudflib::socket_low_level::init(bool _use_zmq_socket_locks) { - use_zmq_socket_locks = _use_zmq_socket_locks; -} - -void exaudflib::socket_low_level::socket_send(zmq::socket_t &socket, zmq::message_t &zmsg) { - DBG_FUNC_BEGIN(std::cerr); -#ifdef LOG_COMMUNICATION - stringstream sb; - uint32_t len = zmsg.size(); - sb << "/tmp/zmqcomm_log_" << ::getpid() << "_send.data"; - int fd = ::open(sb.str().c_str(), O_CREAT | O_APPEND | O_WRONLY, 00644); - if (fd >= 0) { - if (::write(fd, &len, sizeof(uint32_t)) == -1 ) {perror("Log communication");} - if (::write(fd, zmsg.data(), len) == -1) {perror("Log communication");} - ::close(fd); - } -#endif - for (;;) { - try { - if (use_zmq_socket_locks) { - zmq_socket_mutex.lock(); - } - if (socket.send(zmsg) == true) { - if (use_zmq_socket_locks) { - zmq_socket_mutex.unlock(); - } - return; - } - exaudflib::check::external_process_check(); - } catch (std::exception &err) { - exaudflib::check::external_process_check(); - } catch (...) { - exaudflib::check::external_process_check(); - } - if (use_zmq_socket_locks) { - zmq_socket_mutex.unlock(); - } - ::usleep(100000); - } - if (use_zmq_socket_locks) { - zmq_socket_mutex.unlock(); - } -} - -bool exaudflib::socket_low_level::socket_recv(zmq::socket_t &socket, zmq::message_t &zmsg, bool return_on_error) -{ - DBG_FUNC_BEGIN(std::cerr); - for (;;) { - try { - if (use_zmq_socket_locks) { - zmq_socket_mutex.lock(); - } - if (socket.recv(&zmsg) == true) { -#ifdef LOG_COMMUNICATION - stringstream sb; - uint32_t len = zmsg.size(); - sb << "/tmp/zmqcomm_log_" << ::getpid() << "_recv.data"; - int fd = ::open(sb.str().c_str(), O_CREAT | O_APPEND | O_WRONLY, 00644); - if (fd >= 0) { - if (::write(fd, &len, sizeof(uint32_t)) == -1) {perror("Log communication");} - if (::write(fd, zmsg.data(), len) == -1) {perror("Log communication");} - ::close(fd); - } -#endif - if (use_zmq_socket_locks) { - zmq_socket_mutex.unlock(); - } - return true; - } - exaudflib::check::external_process_check(); - } catch (std::exception &err) { - exaudflib::check::external_process_check(); - - } catch (...) { - exaudflib::check::external_process_check(); - } - if (use_zmq_socket_locks) { - zmq_socket_mutex.unlock(); - } - if (return_on_error) return false; - ::usleep(100000); - } - if (use_zmq_socket_locks) { - zmq_socket_mutex.unlock(); - } - return false; -} \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/impl/socket_low_level.h b/exaudfclient/base/exaudflib/impl/socket_low_level.h deleted file mode 100644 index 1e4bd45..0000000 --- a/exaudfclient/base/exaudflib/impl/socket_low_level.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef EXAUDFCLIENT_EXAUDFLIB_SOCKET_LOW_LEVEL_H -#define EXAUDFCLIENT_EXAUDFLIB_SOCKET_LOW_LEVEL_H - -#include - -namespace exaudflib { - namespace socket_low_level { - void init(bool use_zmq_socket_locks); - void socket_send(zmq::socket_t &socket, zmq::message_t &zmsg); - bool socket_recv(zmq::socket_t &socket, zmq::message_t &zmsg, bool return_on_error=false); - } -} - - -#endif //EXAUDFCLIENT_EXAUDFLIB_SOCKET_LOW_LEVEL_H diff --git a/exaudfclient/base/exaudflib/impl/swig/swig_factory.cc b/exaudfclient/base/exaudflib/impl/swig/swig_factory.cc deleted file mode 100644 index 9de8401..0000000 --- a/exaudfclient/base/exaudflib/impl/swig/swig_factory.cc +++ /dev/null @@ -1,19 +0,0 @@ -#include "exaudflib/impl/swig/swig_meta_data.h" -#include "exaudflib/impl/swig/swig_table_iterator.h" -#include "exaudflib/impl/swig/swig_result_handler.h" - -extern "C" { - -SWIGVMContainers::SWIGMetadataIf* create_SWIGMetaData() { - return new SWIGVMContainers::SWIGMetadata_Impl(); -} - -SWIGVMContainers::AbstractSWIGTableIterator* create_SWIGTableIterator() { - return new SWIGVMContainers::SWIGTableIterator_Impl(); -} - -SWIGVMContainers::SWIGRAbstractResultHandler* create_SWIGResultHandler(SWIGVMContainers::SWIGTableIterator* table_iterator) { - return new SWIGVMContainers::SWIGResultHandler_Impl(table_iterator); -} - -} //extern "C" \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/impl/swig/swig_general_iterator.cc b/exaudfclient/base/exaudflib/impl/swig/swig_general_iterator.cc deleted file mode 100644 index ec1ffcf..0000000 --- a/exaudfclient/base/exaudflib/impl/swig/swig_general_iterator.cc +++ /dev/null @@ -1,3 +0,0 @@ -//Check that swig_generial_iterator.h is self-contained -#include "exaudflib/impl/swig/swig_general_iterator.h" - diff --git a/exaudfclient/base/exaudflib/impl/swig/swig_general_iterator.h b/exaudfclient/base/exaudflib/impl/swig/swig_general_iterator.h deleted file mode 100644 index 781274c..0000000 --- a/exaudfclient/base/exaudflib/impl/swig/swig_general_iterator.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef EXAUDFCLIENT_SWIGGENERALITERATOR_H -#define EXAUDFCLIENT_SWIGGENERALITERATOR_H - -#include "exaudflib/swig/swig_common.h" -#include "exaudflib/impl/global.h" - -namespace SWIGVMContainers { - -class SWIGGeneralIterator { -protected: - SWIGVMExceptionHandler *m_exch; -public: - // SWIGGeneralIterator(SWIGVMExceptionHandler *exch): m_exch(exch) { } - SWIGGeneralIterator() - : m_exch(&exaudflib::global.exchandler) - {} - virtual ~SWIGGeneralIterator() { } - inline const char* checkException() { - if (m_exch->exthrowed) { - m_exch->exthrowed = false; - return m_exch->exmsg.c_str(); - } else return NULL; - } -}; - -} //namespace SWIGVMContainers - -#endif //EXAUDFCLIENT_SWIGGENERALITERATOR_H diff --git a/exaudfclient/base/exaudflib/impl/swig/swig_meta_data.cc b/exaudfclient/base/exaudflib/impl/swig/swig_meta_data.cc deleted file mode 100644 index 0a100b7..0000000 --- a/exaudfclient/base/exaudflib/impl/swig/swig_meta_data.cc +++ /dev/null @@ -1,3 +0,0 @@ -//Check that swig_meta_data.h is self-contained -#include "exaudflib/impl/swig/swig_meta_data.h" - diff --git a/exaudfclient/base/exaudflib/impl/swig/swig_meta_data.h b/exaudfclient/base/exaudflib/impl/swig/swig_meta_data.h deleted file mode 100644 index bb0f821..0000000 --- a/exaudfclient/base/exaudflib/impl/swig/swig_meta_data.h +++ /dev/null @@ -1,240 +0,0 @@ -#ifndef EXAUDFCLIENT_SWIGMETADATA_H -#define EXAUDFCLIENT_SWIGMETADATA_H - -#include "exaudflib/swig/swig_common.h" -#include "exaudflib/swig/swig_meta_data.h" -#include "exaudflib/zmqcontainer.pb.h" -#include "exaudflib/impl/socket_low_level.h" -#include "exaudflib/impl/msg_conversion.h" -#include "exaudflib/impl/global.h" -#include -#include -#include - -namespace SWIGVMContainers { - -class SWIGMetadata_Impl : public SWIGMetadataIf { -public: - SWIGMetadata_Impl(): - m_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id), - m_socket(*(exaudflib::global.sock)), - m_exch(&exaudflib::global.exchandler), - m_db_name(exaudflib::global.SWIGVM_params_ref->dbname), - m_db_version(exaudflib::global.SWIGVM_params_ref->dbversion), - m_script_name(exaudflib::global.SWIGVM_params_ref->script_name), - m_script_schema(exaudflib::global.SWIGVM_params_ref->script_schema), - m_current_user(exaudflib::global.SWIGVM_params_ref->current_user), - m_current_schema(exaudflib::global.SWIGVM_params_ref->current_schema), - m_scope_user(exaudflib::global.SWIGVM_params_ref->scope_user), - m_script_code(exaudflib::global.SWIGVM_params_ref->script_code), - m_session_id(exaudflib::global.SWIGVM_params_ref->session_id), - m_statement_id(exaudflib::global.SWIGVM_params_ref->statement_id), - m_node_count(exaudflib::global.SWIGVM_params_ref->node_count), - m_node_id(exaudflib::global.SWIGVM_params_ref->node_id), - m_vm_id(exaudflib::global.SWIGVM_params_ref->vm_id), - m_input_names(*(exaudflib::global.SWIGVM_params_ref->inp_names)), - m_input_types(*(exaudflib::global.SWIGVM_params_ref->inp_types)), - m_input_iter_type(exaudflib::global.SWIGVM_params_ref->inp_iter_type), - m_output_names(*(exaudflib::global.SWIGVM_params_ref->out_names)), - m_output_types(*(exaudflib::global.SWIGVM_params_ref->out_types)), - m_output_iter_type(exaudflib::global.SWIGVM_params_ref->out_iter_type), - m_memory_limit(exaudflib::global.SWIGVM_params_ref->maximal_memory_limit), - m_vm_type(exaudflib::global.SWIGVM_params_ref->vm_type), - m_is_emitted(*(exaudflib::global.SWIGVM_params_ref->is_emitted)), - m_pluginLanguageName(exaudflib::global.SWIGVM_params_ref->pluginName), - m_pluginURI(exaudflib::global.SWIGVM_params_ref->pluginURI), - m_outputAddress(exaudflib::global.SWIGVM_params_ref->outputAddress) - { - { std::stringstream sb; sb << m_session_id; m_session_id_s = sb.str(); } - { std::stringstream sb; sb << m_vm_id; m_vm_id_s = sb.str(); } - } - - virtual ~SWIGMetadata_Impl() { } - inline const char* databaseName() { return m_db_name.c_str(); } - inline const char* databaseVersion() { return m_db_version.c_str(); } - inline const char* scriptName() { return m_script_name.c_str(); } - inline const char* scriptSchema() { return m_script_schema.c_str(); } - inline const char* currentUser() { return m_current_user.c_str(); } - inline const char* scopeUser() { return m_scope_user.c_str(); } - inline const char* currentSchema() {return m_current_schema.c_str();} - inline const char* scriptCode() { return m_script_code.c_str(); } - inline const unsigned long long sessionID() { return m_session_id; } - inline const char *sessionID_S() { return m_session_id_s.c_str(); } - inline const unsigned long statementID() { return m_statement_id; } - inline const unsigned int nodeCount() { return m_node_count; } - inline const unsigned int nodeID() { return m_node_id; } - inline const unsigned long long vmID() { return m_vm_id; } - inline const unsigned long long memoryLimit() { return m_memory_limit; } - inline const VMTYPE vmType() { return m_vm_type; } - inline const char *vmID_S() { return m_vm_id_s.c_str(); } - inline const ExecutionGraph::ConnectionInformationWrapper* connectionInformation(const char* connection_name) - { - exascript_request request; - request.set_type(MT_IMPORT); - request.set_connection_id(m_connection_id); - exascript_import_req *req = request.mutable_import(); - req->set_script_name(connection_name); - req->set_kind(PB_IMPORT_CONNECTION_INFORMATION); - if (!request.SerializeToString(&m_output_buffer)) { - m_exch->setException("F-UDF-CL-LIB-1048: Communication error: failed to serialize data"); - return new ExecutionGraph::ConnectionInformationWrapper(ExecutionGraph::ConnectionInformation()); - } - zmq::message_t zmsg_req((void*)m_output_buffer.c_str(), m_output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(m_socket, zmsg_req); - zmq::message_t zmsg_rep; - exaudflib::socket_low_level::socket_recv(m_socket, zmsg_rep); - exascript_response response; - if (!response.ParseFromArray(zmsg_rep.data(), zmsg_rep.size())) { - m_exch->setException("F-UDF-CL-LIB-1049: Communication error: failed to parse data"); - return new ExecutionGraph::ConnectionInformationWrapper(ExecutionGraph::ConnectionInformation()); - } - if (response.type() != MT_IMPORT) { - m_exch->setException("F-UDF-CL-LIB-1050: Internal error: wrong message type, got "+ - exaudflib::msg_conversion::convert_message_type_to_string(response.type())); - return new ExecutionGraph::ConnectionInformationWrapper(ExecutionGraph::ConnectionInformation()); - } - const exascript_import_rep &rep = response.import(); - if (rep.has_exception_message()) { - m_exch->setException(rep.exception_message().c_str()); - return new ExecutionGraph::ConnectionInformationWrapper(ExecutionGraph::ConnectionInformation()); - } - if (!rep.has_connection_information()) { - m_exch->setException("F-UDF-CL-LIB-1051: Internal error: No connection information returned"); - return new ExecutionGraph::ConnectionInformationWrapper(ExecutionGraph::ConnectionInformation()); - } - connection_information_rep ci = rep.connection_information(); - return new ExecutionGraph::ConnectionInformationWrapper( - ExecutionGraph::ConnectionInformation(ci.kind(), ci.address(), ci.user(), ci.password())); - } - inline const char* moduleContent(const char* name) { - exascript_request request; - request.set_type(MT_IMPORT); - request.set_connection_id(m_connection_id); - exascript_import_req *req = request.mutable_import(); - req->set_script_name(name); - req->set_kind(PB_IMPORT_SCRIPT_CODE); - if (!request.SerializeToString(&m_output_buffer)) { - m_exch->setException("F-UDF-CL-LIB-1052: Communication error: failed to serialize data"); - return NULL; - } - zmq::message_t zmsg_req((void*)m_output_buffer.c_str(), m_output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(m_socket, zmsg_req); - zmq::message_t zmsg_rep; - exaudflib::socket_low_level::socket_recv(m_socket, zmsg_rep); - exascript_response response; - if (!response.ParseFromArray(zmsg_rep.data(), zmsg_rep.size())) { - m_exch->setException("F-UDF-CL-LIB-1053: Communication error: failed to parse data"); - return NULL; - } - if (response.type() != MT_IMPORT) { - m_exch->setException("F-UDF-CL-LIB-1054: Internal error: wrong message type, should MT_IMPORT, got "+ - exaudflib::msg_conversion::convert_message_type_to_string(response.type())); - return NULL; - } - const exascript_import_rep &rep = response.import(); - if (rep.has_exception_message()) { - m_exch->setException(rep.exception_message().c_str()); - return NULL; - } - if (!rep.has_source_code()) { - m_exch->setException("F-UDF-CL-LIB-1055: Internal error: No source code returned"); - return NULL; - } - m_temp_code = rep.source_code(); - return m_temp_code.c_str(); - } - inline const unsigned int inputColumnCount() { return m_input_names.size(); } - inline const char *inputColumnName(unsigned int col) - { return col >= m_input_names.size() ? NULL : m_input_names[col].c_str(); } - inline const SWIGVM_datatype_e inputColumnType(unsigned int col) - { return col >= m_input_types.size() ? UNSUPPORTED : m_input_types[col].type; } - inline const char *inputColumnTypeName(unsigned int col) - { return col >= m_input_types.size() ? NULL : m_input_types[col].type_name.c_str(); } - inline const unsigned int inputColumnSize(unsigned int col) - { return col >= m_input_types.size() ? 0 : m_input_types[col].len; } - inline const unsigned int inputColumnPrecision(unsigned int col) - { return col >= m_input_types.size() ? 0 : m_input_types[col].prec; } - inline const unsigned int inputColumnScale(unsigned int col) - { return col >= m_input_types.size() ? 0 : m_input_types[col].scale; } - inline const SWIGVM_itertype_e inputType() { return m_input_iter_type; } - inline const unsigned int outputColumnCount() { return m_output_names.size(); } - inline const char *outputColumnName(unsigned int col) { - if (m_output_iter_type == EXACTLY_ONCE && col == 0) - return "RETURN"; - return col >= m_output_names.size() ? NULL : m_output_names[col].c_str(); - } - inline const SWIGVM_datatype_e outputColumnType(unsigned int col) - { return col >= m_output_types.size() ? UNSUPPORTED : m_output_types[col].type; } - inline const char *outputColumnTypeName(unsigned int col) - { return col >= m_output_types.size() ? NULL : m_output_types[col].type_name.c_str(); } - inline const unsigned int outputColumnSize(unsigned int col) - { return col >= m_output_types.size() ? 0 : m_output_types[col].len; } - inline const unsigned int outputColumnPrecision(unsigned int col) - { return col >= m_output_types.size() ? 0 : m_output_types[col].prec; } - inline const unsigned int outputColumnScale(unsigned int col) - { return col >= m_output_types.size() ? 0 : m_output_types[col].scale; } - inline const SWIGVM_itertype_e outputType() { return m_output_iter_type; } - inline const bool isEmittedColumn(unsigned int col){ - if (col >= m_is_emitted.size()) - { - abort(); - } - return m_is_emitted[col]; - } - inline const char* checkException() { - if (m_exch->exthrowed) { - m_exch->exthrowed = false; - return m_exch->exmsg.c_str(); - } else return NULL; - } - inline const char* pluginLanguageName() - { - return m_pluginLanguageName.c_str(); - } - inline const char* pluginURI() - { - return m_pluginURI.c_str(); - } - inline const char* outputAddress() - { - return m_outputAddress.c_str(); - } -private: - const uint64_t m_connection_id; - zmq::socket_t &m_socket; - std::string m_output_buffer; - SWIGVMExceptionHandler *m_exch; - const std::string m_db_name; - const std::string m_db_version; - const std::string m_script_name; - const std::string m_script_schema; - const std::string m_current_user; - const std::string m_current_schema; - const std::string m_scope_user; - const std::string m_script_code; - const unsigned long m_session_id; - const unsigned long m_statement_id; - const unsigned int m_node_count; - const unsigned int m_node_id; - const unsigned long m_vm_id; - std::string m_temp_code; - const std::vector &m_input_names; - const std::vector &m_input_types; - const SWIGVM_itertype_e m_input_iter_type; - const std::vector &m_output_names; - const std::vector &m_output_types; - const SWIGVM_itertype_e m_output_iter_type; - const unsigned long long m_memory_limit; - const std::string m_meta_info; - const VMTYPE m_vm_type; - std::string m_session_id_s; - std::string m_vm_id_s; - const std::vector &m_is_emitted; - std::string m_pluginLanguageName; - std::string m_pluginURI; - std::string m_outputAddress; -}; - -} //namespace SWIGVMContainers - -#endif //EXAUDFCLIENT_SWIGMETADATA_H diff --git a/exaudfclient/base/exaudflib/impl/swig/swig_result_handler.cc b/exaudfclient/base/exaudflib/impl/swig/swig_result_handler.cc deleted file mode 100644 index 987b5e3..0000000 --- a/exaudfclient/base/exaudflib/impl/swig/swig_result_handler.cc +++ /dev/null @@ -1,3 +0,0 @@ -//Check that swig_result_handler.h is self-contained -#include "exaudflib/impl/swig/swig_result_handler.h" - diff --git a/exaudfclient/base/exaudflib/impl/swig/swig_result_handler.h b/exaudfclient/base/exaudflib/impl/swig/swig_result_handler.h deleted file mode 100644 index cb143db..0000000 --- a/exaudfclient/base/exaudflib/impl/swig/swig_result_handler.h +++ /dev/null @@ -1,282 +0,0 @@ -#ifndef EXAUDFCLIENT_SWIGRESULTHANDLER_H -#define EXAUDFCLIENT_SWIGRESULTHANDLER_H - -#include "exaudflib/swig/swig_common.h" -#include "exaudflib/swig/swig_result_handler.h" -#include "exaudflib/impl/swig/swig_general_iterator.h" -#include "exaudflib/impl/global.h" -#include "exaudflib/impl/msg_conversion.h" -#include "exaudflib/impl/socket_low_level.h" -#include "exaudflib/zmqcontainer.pb.h" - -namespace SWIGVMContainers { - -class SWIGResultHandler_Impl : public SWIGRAbstractResultHandler, SWIGGeneralIterator { -private: - SWIGTableIterator* m_table_iterator; - const uint64_t m_connection_id; - zmq::socket_t &m_socket; - std::string m_output_buffer; - uint64_t m_message_size; - struct rowdata_t { - std::map null_data; - std::map bool_data; - std::map double_data; - std::map int32_data; - std::map int64_data; - std::map string_data; - }; - rowdata_t m_rowdata; - exascript_request m_emit_request; - uint64_t m_rows_emited; - const std::vector &m_types; -public: - const char* checkException() {return SWIGGeneralIterator::checkException();} - SWIGResultHandler_Impl(SWIGTableIterator* table_iterator) - : m_table_iterator(table_iterator), - m_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id), - m_socket(*(exaudflib::global.sock)), - m_message_size(0), - m_rows_emited(1), - m_types(*(exaudflib::global.SWIGVM_params_ref->out_types)) - {} - - ~SWIGResultHandler_Impl() {} - inline void reinitialize() { - m_rows_emited = 0; - m_message_size = 0; - m_emit_request.Clear(); - m_rowdata = rowdata_t(); - } - inline unsigned long rowsEmited() { - return m_rows_emited; - } - inline void flush() { - exascript_emit_data_req *req = m_emit_request.mutable_emit(); - exascript_table_data *table = req->mutable_table(); - if (table->has_rows() && table->rows() > 0) { - { m_emit_request.set_type(MT_EMIT); - m_emit_request.set_connection_id(m_connection_id); - if (!m_emit_request.SerializeToString(&m_output_buffer)) { - m_exch->setException("F-UDF-CL-LIB-1082: Communication error: failed to serialize data"); - return; - } - zmq::message_t zmsg((void*)m_output_buffer.c_str(), m_output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(m_socket, zmsg); - m_emit_request.Clear(); - m_message_size = 0; - } - { zmq::message_t zmsg; - exaudflib::socket_low_level::socket_recv(m_socket, zmsg); - exascript_response response; - if (!response.ParseFromArray(zmsg.data(), zmsg.size())) { - m_exch->setException("F-UDF-CL-LIB-1083: Communication error: failed to parse data"); - return; - } - if (response.connection_id() != m_connection_id) { - std::stringstream sb; - sb << "F-UDF-CL-LIB-1084: Received wrong connection id " << response.connection_id() - << ", should be " << m_connection_id; - m_exch->setException(sb.str().c_str()); - return; - } - if (response.type() == MT_CLOSE) { - if (!response.close().has_exception_message()) - m_exch->setException("F-UDF-CL-LIB-1085: Unknown error occured"); - else - m_exch->setException(response.close().exception_message().c_str()); - return; - } - if (response.type() != MT_EMIT) { - m_exch->setException("F-UDF-CL-LIB-1086: Wrong response type, got "+ - exaudflib::msg_conversion::convert_message_type_to_string(response.type())); - return; - } - } - } - } - inline bool next() { - ++m_rows_emited; - exascript_emit_data_req *req = m_emit_request.mutable_emit(); - exascript_table_data *table = req->mutable_table(); - for (unsigned int col = 0; col < m_types.size(); ++col) { - bool null_data = m_rowdata.null_data[col]; - table->add_data_nulls(null_data); - if (null_data) continue; - switch (m_types[col].type) { - case UNSUPPORTED: - m_exch->setException("F-UDF-CL-LIB-1087: Unsupported data type found"); - return false; - case DOUBLE: - if (m_rowdata.double_data.find(col) == m_rowdata.double_data.end()) { - m_exch->setException("F-UDF-CL-LIB-1088: Not enough double columns emited"); - return false; - } - m_message_size += sizeof(double); - table->add_data_double(m_rowdata.double_data[col]); - break; - case INT32: - if (m_rowdata.int32_data.find(col) == m_rowdata.int32_data.end()) { - m_exch->setException("F-UDF-CL-LIB-1089: Not enough int32 columns emited"); - return false; - } - m_message_size += sizeof(int32_t); - table->add_data_int32(m_rowdata.int32_data[col]); - break; - case INT64: - if (m_rowdata.int64_data.find(col) == m_rowdata.int64_data.end()) { - m_exch->setException("F-UDF-CL-LIB-1090: Not enough int64 columns emited"); - return false; - } - m_message_size += sizeof(int64_t); - table->add_data_int64(m_rowdata.int64_data[col]); - break; - case NUMERIC: - case TIMESTAMP: - case DATE: - case STRING: - if (m_rowdata.string_data.find(col) == m_rowdata.string_data.end()) { - m_exch->setException("F-UDF-CL-LIB-1091: Not enough string columns emited"); - return false; - } - m_message_size += sizeof(int32_t) + m_rowdata.string_data[col].length(); - *table->add_data_string() = m_rowdata.string_data[col]; - break; - case BOOLEAN: - if (m_rowdata.bool_data.find(col) == m_rowdata.bool_data.end()) { - m_exch->setException("F-UDF-CL-LIB-1092: Not enough boolean columns emited"); - return false; - } - m_message_size += 1; - table->add_data_bool(m_rowdata.bool_data[col]); - break; - default: - m_exch->setException("F-UDF-CL-LIB-1093: Unknown data type found, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - return false; - } - } - table->add_row_number(m_table_iterator->get_current_row()); - m_rowdata = rowdata_t(); - if (!table->has_rows()) table->set_rows(1); - else table->set_rows(table->rows() + 1); - table->set_rows_in_group(0); - if (m_message_size >= SWIG_MAX_VAR_DATASIZE) { - if (exaudflib::global.SWIGVM_params_ref->inp_iter_type == EXACTLY_ONCE && exaudflib::global.SWIGVM_params_ref->out_iter_type == EXACTLY_ONCE) - exaudflib::global.SWIGVM_params_ref->inp_force_finish = true; - else this->flush(); - } - return true; - } - inline void setDouble(unsigned int col, const double v) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1094: Output column does "+std::to_string(col)+" not exist"); - return; - } - if (m_types[col].type != DOUBLE) { - m_exch->setException("E-UDF-CL-LIB-1095: Wrong output column type, expected DOUBLE, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - return; - } - m_rowdata.null_data[col] = false; - m_rowdata.double_data[col] = v; - } - inline void setString(unsigned int col, const char *v, size_t l) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1096: Output column does "+std::to_string(col)+" not exist"); - return; - } - if (m_types[col].type != STRING) { - m_exch->setException("E-UDF-CL-LIB-1097: Wrong output column type, expected STRING, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - return; - } - m_rowdata.null_data[col] = false; - m_rowdata.string_data[col] = v; - } - inline void setInt32(unsigned int col, const int32_t v) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1098: Output column does "+std::to_string(col)+" not exist"); - return; - } - if (m_types[col].type != INT32) { - m_exch->setException("E-UDF-CL-LIB-1099: Wrong output column type, expected INT32, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - return; - } - m_rowdata.null_data[col] = false; - m_rowdata.int32_data[col] = v; - } - inline void setInt64(unsigned int col, const int64_t v) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1100: Output column does "+std::to_string(col)+" not exist"); - return; - } - if (m_types[col].type != INT64) { - m_exch->setException("E-UDF-CL-LIB-1101: Wrong output column type, expected INT64, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - return; - } - m_rowdata.null_data[col] = false; - m_rowdata.int64_data[col] = v; - } - inline void setNumeric(unsigned int col, const char *v) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1102: Output column does "+std::to_string(col)+" not exist"); - return; - } - if (m_types[col].type != NUMERIC) { - m_exch->setException("E-UDF-CL-LIB-1103: Wrong output column type, expected NUMERIC, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - return; - } - m_rowdata.null_data[col] = false; - m_rowdata.string_data[col] = v; - } - inline void setTimestamp(unsigned int col, const char *v) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1104: Output column does "+std::to_string(col)+" not exist"); - return; - } - if (m_types[col].type != TIMESTAMP) { - m_exch->setException("E-UDF-CL-LIB-1105: Wrong output column type, expected TIMESTAMP, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - return; - } - m_rowdata.null_data[col] = false; - m_rowdata.string_data[col] = v; - } - inline void setDate(unsigned int col, const char *v) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1106: Output column does "+std::to_string(col)+" not exist"); - return; - } - if (m_types[col].type != DATE) { - m_exch->setException("E-UDF-CL-LIB-1107: Wrong output column type, expected DATE, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - return; - } - m_rowdata.null_data[col] = false; - m_rowdata.string_data[col] = v; - } - inline void setBoolean(unsigned int col, const bool v) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1108: Output column does "+std::to_string(col)+" not exist"); - return; - } - if (m_types[col].type != BOOLEAN) { - m_exch->setException("E-UDF-CL-LIB-1109: Wrong output column type, expected BOOLEAN, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - return; - } - m_rowdata.null_data[col] = false; - m_rowdata.bool_data[col] = v; - } - inline void setNull(unsigned int col) { - m_rowdata.null_data[col] = true; - } -}; - -} //namespace SWIGVMContainers - -#endif //EXAUDFCLIENT_SWIGRESULTHANDLER_H diff --git a/exaudfclient/base/exaudflib/impl/swig/swig_table_iterator.cc b/exaudfclient/base/exaudflib/impl/swig/swig_table_iterator.cc deleted file mode 100644 index 853e79e..0000000 --- a/exaudfclient/base/exaudflib/impl/swig/swig_table_iterator.cc +++ /dev/null @@ -1,3 +0,0 @@ -//Check that swig_table_iterator.h is self-contained -#include "exaudflib/impl/swig/swig_table_iterator.h" - diff --git a/exaudfclient/base/exaudflib/impl/swig/swig_table_iterator.h b/exaudfclient/base/exaudflib/impl/swig/swig_table_iterator.h deleted file mode 100644 index bf5f014..0000000 --- a/exaudfclient/base/exaudflib/impl/swig/swig_table_iterator.h +++ /dev/null @@ -1,346 +0,0 @@ -#ifndef EXAUDFCLIENT_SWIGTABLEITERATOR_H -#define EXAUDFCLIENT_SWIGTABLEITERATOR_H - -#include "exaudflib/swig/swig_common.h" -#include "exaudflib/swig/swig_table_iterator.h" -#include "exaudflib/impl/swig/swig_general_iterator.h" -#include "exaudflib/impl/global.h" -#include "exaudflib/impl/socket_low_level.h" -#include "exaudflib/impl/msg_conversion.h" - -namespace SWIGVMContainers { - -class SWIGTableIterator_Impl : public AbstractSWIGTableIterator, SWIGGeneralIterator { -private: - const uint64_t m_connection_id; - zmq::socket_t &m_socket; - std::string m_output_buffer; - exascript_request m_request; - exascript_response m_next_response; - - uint64_t m_rows_received; - struct values_per_row_t { - uint64_t strings, bools, int32s, int64s, doubles; - values_per_row_t(): strings(0), bools(0), int32s(0), int64s(0), doubles(0) {} - void reset() { strings = bools = int32s = int64s = doubles = 0; } - } m_values_per_row; - uint64_t m_column_count; - std::vector m_col_offsets; - uint64_t m_rows_in_group; - uint64_t m_current_row; - uint64_t m_rows_completed; - uint64_t m_rows_group_completed; - bool m_was_null; - const std::vector &m_types; - void increment_col_offsets(bool reset = false) { - m_current_row = m_next_response.next().table().row_number(m_rows_completed); - uint64_t current_column = 0; - ssize_t null_index = 0; - if (reset) m_values_per_row.reset(); - null_index = m_rows_completed * m_column_count; - if (m_next_response.next().table().data_nulls_size() <= (null_index + (ssize_t)m_column_count - 1)) { - std::stringstream sb; - sb << "F-UDF-CL-LIB-1056: Internal error: not enough nulls in packet: wanted index " << (null_index + m_column_count - 1) - << " but have " << m_next_response.next().table().data_nulls_size() - << " elements"; - m_exch->setException(sb.str().c_str()); - return; - } - for (std::vector::const_iterator - it = m_types.begin(); it != m_types.end(); ++it, ++current_column, ++null_index) - { - if (m_next_response.next().table().data_nulls(null_index)) - continue; - switch (it->type) { - case UNSUPPORTED: m_exch->setException("F-UDF-CL-LIB-1057: Unsupported data type found"); return; - case DOUBLE: m_col_offsets[current_column] = m_values_per_row.doubles++; break; - case INT32: m_col_offsets[current_column] = m_values_per_row.int32s++; break; - case INT64: m_col_offsets[current_column] = m_values_per_row.int64s++; break; - case NUMERIC: - case TIMESTAMP: - case DATE: - case STRING: m_col_offsets[current_column] = m_values_per_row.strings++; break; - case BOOLEAN: m_col_offsets[current_column] = m_values_per_row.bools++; break; - default: m_exch->setException("F-UDF-CL-LIB-1058: Unknown data type found, got "+it->type); return; - } - } - } - void receive_next_data(bool reset) { - m_rows_received = 0; - m_rows_completed = 0; - { - m_request.Clear(); - m_request.set_connection_id(m_connection_id); - if (reset) m_request.set_type(MT_RESET); - else m_request.set_type(MT_NEXT); - if(!m_request.SerializeToString(&m_output_buffer)) { - m_exch->setException("F-UDF-CL-LIB-1059: Communication error: failed to serialize data"); - return; - } - zmq::message_t zmsg((void*)m_output_buffer.c_str(), m_output_buffer.length(), NULL, NULL); - exaudflib::socket_low_level::socket_send(m_socket, zmsg); - } { - zmq::message_t zmsg; - exaudflib::socket_low_level::socket_recv(m_socket, zmsg); - m_next_response.Clear(); - if (!m_next_response.ParseFromArray(zmsg.data(), zmsg.size())) { - m_exch->setException("F-UDF-CL-LIB-1060: Communication error: failed to parse data"); - return; - } - if (m_next_response.connection_id() != m_connection_id) { - std::stringstream sb; - sb << "F-UDF-CL-LIB-1061: Communication error: wrong connection id, expected " - << m_connection_id << " got " << m_next_response.connection_id(); - m_exch->setException(sb.str()); - return; - } - if (m_next_response.type() == MT_DONE) { - return; - } - if (m_next_response.type() == MT_CLOSE) { - const exascript_close &rep = m_next_response.close(); - if (!rep.has_exception_message()) { - if (m_rows_completed == 0) { - return; - } else m_exch->setException("F-UDF-CL-LIB-1062: Unknown error occured"); - } else { - m_exch->setException(rep.exception_message().c_str()); - } - return; - } - if ((reset && (m_next_response.type() != MT_RESET)) || - (!reset && (m_next_response.type() != MT_NEXT))) - { - m_exch->setException("F-UDF-CL-LIB-1063: Communication error: wrong message type, got "+ - exaudflib::msg_conversion::convert_message_type_to_string(m_next_response.type())); - return; - } - m_rows_received = m_next_response.next().table().rows(); - m_rows_in_group = m_next_response.next().table().rows_in_group(); - } - increment_col_offsets(true); - } - inline ssize_t check_index(ssize_t index, ssize_t available, const char *tp, const char *otype, const char *ts) { - if (available > index) return index; - std::stringstream sb; - sb << "F-UDF-CL-LIB-1064: Internal error: not enough " << tp << otype << ts << " in packet: wanted index " - << index << " but have " << available << " elements (on " - << m_rows_received << '/' << m_rows_completed << " of received/completed rows"; - m_exch->setException(sb.str().c_str()); - m_was_null = true; - return -1; - } - inline ssize_t check_value(unsigned int col, ssize_t available, const char *otype) { - m_was_null = false; - ssize_t index = check_index(m_column_count * m_rows_completed + col, - m_next_response.next().table().data_nulls_size(), - "nulls for ", otype, ""); - if (m_was_null) return -1; - m_was_null = m_next_response.next().table().data_nulls(index); - if (m_was_null) return -1; - index = check_index(m_col_offsets[col], available, "", otype, "s"); - if (m_was_null) return -1; - return index; - } -public: - const char* checkException() {return SWIGGeneralIterator::checkException();} - - SWIGTableIterator_Impl(): - m_connection_id(exaudflib::global.SWIGVM_params_ref->connection_id), - m_socket(*(exaudflib::global.sock)), - m_column_count(exaudflib::global.SWIGVM_params_ref->inp_types->size()), - m_col_offsets(exaudflib::global.SWIGVM_params_ref->inp_types->size()), - m_current_row((uint64_t)-1), - m_rows_completed(0), - m_rows_group_completed(1), - m_was_null(false), - m_types(*(exaudflib::global.SWIGVM_params_ref->inp_types)) - { - receive_next_data(false); - } - ~SWIGTableIterator_Impl() {} - uint64_t get_current_row() - { - return m_current_row; - } - inline void reinitialize() { - m_rows_completed = 0; - m_rows_group_completed = 1; - m_values_per_row.reset(); - receive_next_data(false); - } - inline bool next() { - if (m_rows_received == 0) { - m_exch->setException("E-UDF-CL-LIB-1065: Iteration finished"); - return false; - } - ++m_rows_completed; - ++m_rows_group_completed; - if (exaudflib::global.SWIGVM_params_ref->inp_force_finish) - return false; - if (m_rows_completed >= m_rows_received) { - receive_next_data(false); - if (m_rows_received == 0) - return false; - else return true; - } - increment_col_offsets(); - return true; - } - inline bool eot() { - return m_rows_received == 0; - } - inline void reset() { - m_rows_group_completed = 1; - exaudflib::global.SWIGVM_params_ref->inp_force_finish = false; - receive_next_data(true); - } - inline unsigned long restBufferSize() { - if (m_rows_completed < m_rows_received) - return m_rows_received - m_rows_completed; - return 0; - } - inline unsigned long rowsCompleted() { - return m_rows_group_completed; - } - inline unsigned long rowsInGroup() { - return m_rows_in_group; - } - inline double getDouble(unsigned int col) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1066: Input column "+std::to_string(col)+" does not exist"); - m_was_null = true; - return 0.0; - } - if (m_types[col].type != DOUBLE) { - m_exch->setException("E-UDF-CL-LIB-1067: Wrong input column type, expected DOUBLE, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - m_was_null = true; - return 0.0; - } - ssize_t index = check_value(col, m_next_response.next().table().data_double_size(), "double"); - if (m_was_null) { - return 0.0; - } - return m_next_response.next().table().data_double(index); - } - inline const char *getString(unsigned int col, size_t *length = NULL) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1068: Input column "+std::to_string(col)+" does not exist"); - m_was_null = true; - return ""; - } - if (m_types[col].type != STRING) { - m_exch->setException("E-UDF-CL-LIB-1069: Wrong input column type, expected STRING, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - m_was_null = true; - return ""; - } - ssize_t index = check_value(col, m_next_response.next().table().data_string_size(), "string"); - if (m_was_null) return ""; - const std::string &s(m_next_response.next().table().data_string(index)); - if (length != NULL) *length = s.length(); - return s.c_str(); - } - inline int32_t getInt32(unsigned int col) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1070: Input column "+std::to_string(col)+" does not exist"); - m_was_null = true; - return 0; - } - if (m_types[col].type != INT32) { - m_exch->setException("E-UDF-CL-LIB-1071: Wrong input column type, expected INT32, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - m_was_null = true; - return 0; - } - ssize_t index = check_value(col, m_next_response.next().table().data_int32_size(), "int32"); - if (m_was_null) return 0; - return m_next_response.next().table().data_int32(index); - } - inline int64_t getInt64(unsigned int col) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1072: Input column "+std::to_string(col)+" does not exist"); - m_was_null = true; - return 0LL; - } - if (m_types[col].type != INT64) { - m_exch->setException("E-UDF-CL-LIB-1073: Wrong input column type, expected INT64, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - m_was_null = true; - return 0LL; - } - ssize_t index = check_value(col, m_next_response.next().table().data_int64_size(), "int64"); - if (m_was_null) return 0LL; - return m_next_response.next().table().data_int64(index); - } - inline const char *getNumeric(unsigned int col) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1074: Input column "+std::to_string(col)+" does not exist"); - m_was_null = true; - return ""; - } - if (m_types[col].type != NUMERIC) { - m_exch->setException("E-UDF-CL-LIB-1075: Wrong input column type, expected NUMERIC, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - m_was_null = true; - return ""; - } - ssize_t index = check_value(col, m_next_response.next().table().data_string_size(), "string"); - if (m_was_null) return "0"; - return m_next_response.next().table().data_string(index).c_str(); - } - inline const char *getTimestamp(unsigned int col) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1076: Input column "+std::to_string(col)+" does not exist"); - m_was_null = true; - return ""; - } - if (m_types[col].type != TIMESTAMP) { - m_exch->setException("E-UDF-CL-LIB-1077: Wrong input column type, expected TIMESTAMP, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - m_was_null = true; - return ""; - } - ssize_t index = check_value(col, m_next_response.next().table().data_string_size(), "string"); - if (m_was_null) return "1970-01-01 00:00:00.00 0000"; - return m_next_response.next().table().data_string(index).c_str(); - } - inline const char *getDate(unsigned int col) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1078: Input column "+std::to_string(col)+" does not exist"); - m_was_null = true; - return ""; - } - if (m_types[col].type != DATE) { - m_exch->setException("E-UDF-CL-LIB-1079: Wrong input column type, expected DATE, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - m_was_null = true; - return ""; - } - ssize_t index = check_value(col, m_next_response.next().table().data_string_size(), "string"); - if (m_was_null) return "1970-01-01"; - return m_next_response.next().table().data_string(index).c_str(); - } - inline bool getBoolean(unsigned int col) { - if (col >= m_types.size()) { - m_exch->setException("E-UDF-CL-LIB-1080: Input column "+std::to_string(col)+" does not exist"); - m_was_null = true; - return ""; - } - if (m_types[col].type != BOOLEAN) { - m_exch->setException("E-UDF-CL-LIB-1081: Wrong input column type, expected BOOLEAN, got "+ - exaudflib::msg_conversion::convert_type_to_string(m_types[col].type)); - m_was_null = true; - return ""; - } - ssize_t index = check_value(col, m_next_response.next().table().data_bool_size(), "bool"); - if (m_was_null) return false; - return m_next_response.next().table().data_bool(index); - } - inline bool wasNull() { return m_was_null; } -}; - -} //namespace SWIGVMContainers - -#endif //EXAUDFCLIENT_SWIGTABLEITERATOR_H diff --git a/exaudfclient/base/exaudflib/load_dynamic.h b/exaudfclient/base/exaudflib/load_dynamic.h deleted file mode 100644 index e3dd47c..0000000 --- a/exaudfclient/base/exaudflib/load_dynamic.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef EXAUDFLIB_LOAD_DYNAMIC -#define EXAUDFLIB_LOAD_DYNAMIC - -void set_exaudflib_handle(void* handle); -void* load_dynamic(const char* name); - -#endif //EXAUDFLIB_LOAD_DYNAMIC \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/swig/script_data_transfer_objects.cc b/exaudfclient/base/exaudflib/swig/script_data_transfer_objects.cc deleted file mode 100644 index 78a890f..0000000 --- a/exaudfclient/base/exaudflib/swig/script_data_transfer_objects.cc +++ /dev/null @@ -1,465 +0,0 @@ -//#ifdef BUILDINSWIGDIR -//#include "scriptDTO.h" -//#else -#include "script_data_transfer_objects.h" -//#endif -#include -#include - -namespace ExecutionGraph -{ - -////////////////////////////// -EmptyDTO::EmptyDTO() -{} - -void EmptyDTO::accept(ScriptDTOSerializer& serializer) const -{ - return; -} - -bool EmptyDTO::isEmpty() const -{ - return true; -} - -////////////////////////////// - - -void StringDTO::accept(ScriptDTOSerializer& serializer) const -{ - serializer.visit(*this); -} - -StringDTO::StringDTO() - : arg("") -{} - -StringDTO::StringDTO(const std::string& arg_) - : arg(arg_) -{} - - -const std::string StringDTO::getArg() const -{ - return arg; -} - -bool StringDTO::isEmpty() const -{ - return false; -} - -////////////////////////////// - - - -void ConnectionInformation::accept(ScriptDTOSerializer& serializer) const -{ - serializer.visit(*this); -} - -ConnectionInformation::ConnectionInformation(const std::string& kind_, const std::string& address_, const std::string& user_, const std::string& password_) - : kind(kind_), - address(address_), - user(user_), - password(password_) -{ -} - -ConnectionInformation::ConnectionInformation(const std::string& address_, const std::string& user_, const std::string& password_) - : kind("password"), - address(address_), - user(user_), - password(password_) -{} - - -ConnectionInformation::ConnectionInformation() - : kind(""), address(""), user(""), password("") -{} - -ConnectionInformation::ConnectionInformation(const ConnectionInformation& other) - : kind(other.getKind()), - address(other.getAddress()), - user(other.getUser()), - password(other.getPassword()) -{} - -const std::string ConnectionInformation::getKind() const -{ - return kind; -} - -const std::string ConnectionInformation::getAddress() const -{ - return address; -} - -const std::string ConnectionInformation::getUser() const -{ - return user; -} - -const std::string ConnectionInformation::getPassword() const -{ - return password; -} - -bool ConnectionInformation::hasData() const -{ - return kind.size() == 0; -} - -bool ConnectionInformation::isEmpty() const -{ - return false; -} - -////////////////////////////// - - -//ImportSpecification::ImportSpecificationError::ImportSpecificationError(const std::string& msg_) -// :msg(msg_) -//{} - -//ImportSpecification::ImportSpecificationError::~ImportSpecificationError() throw() {} - - - -//const char* ImportSpecification::ImportSpecificationError::what() const throw() -//{ -// return msg.c_str(); -//} - - - -ImportSpecification::ImportSpecification() - : isEmptySpec(true) -{} - -ImportSpecification::ImportSpecification(bool isSubselect__) - : isEmptySpec(false), - isSubselect_(isSubselect__), - subselect_column_names(), - subselect_column_types(), - connection_name(""), - connection_information(), - parameters() -{ -} - - -void ImportSpecification::accept(ScriptDTOSerializer& serializer) const -{ - serializer.visit(*this); -} - -bool ImportSpecification::isEmpty() const -{ - return isEmptySpec; -} - - -bool ImportSpecification::isSubselect() const -{ - return isSubselect_; -} -bool ImportSpecification::hasSubselectColumnNames() const -{ - return subselect_column_names.size()>0; -} -bool ImportSpecification::hasSubselectColumnTypes() const -{ - return subselect_column_types.size()>0; -} -bool ImportSpecification::hasSubselectColumnSpecification() const -{ - return hasSubselectColumnNames() || hasSubselectColumnTypes(); -} -bool ImportSpecification::hasConnectionName() const -{ - return connection_name.size()>0; -} -bool ImportSpecification::hasConnectionInformation() const -{ - return connection_information.hasData() == false; -} -bool ImportSpecification::hasParameters() const -{ - return parameters.size()>0; -} -bool ImportSpecification::hasConsistentColumns() const -{ - return (isSubselect() && subselect_column_names.size() == subselect_column_types.size()) || (!isSubselect() && subselect_column_types.size() == 0); -} - -bool ImportSpecification::isCompleteImportSubselectSpecification() const -{ - return hasConsistentColumns() && hasSubselectColumnNames() && hasSubselectColumnTypes(); -} - -bool ImportSpecification::isCompleteImportIntoTargetTableSpecification() const -{ - return hasConsistentColumns(); -} - - - -const std::vector& ImportSpecification::getSubselectColumnNames() const -{ - if (!isSubselect()) - { - throw Error("import specification error: cannot get column names of non-subselect import specification"); - } - return subselect_column_names; -} - -const std::vector& ImportSpecification::getSubselectColumnTypes() const -{ - if (!isSubselect()) - { - throw Error("import specification error: cannot get column types of non-subselect import specification"); - } - - return subselect_column_types; -} - - -void ImportSpecification::appendSubselectColumnName(const std::string& columnName) -{ - if (!isSubselect()) - { - throw Error("import specification error: cannot add column name to non-subselect import specification"); - } - subselect_column_names.push_back(columnName); -} - -void ImportSpecification::appendSubselectColumnType(const std::string& columnType) -{ - if (!isSubselect()) - { - throw Error("import specification error: cannot add column type to non-subselect import specification"); - } - subselect_column_types.push_back(columnType); -} - -void ImportSpecification::setConnectionName(const std::string& connectionName_) -{ - if (hasConnectionName()) - { - throw Error("import specification error: connection name is set more than once"); - } - if (hasConnectionInformation()) - { - throw Error("import specification error: cannot set connection name, because there is already connection information set"); - } - connection_name = connectionName_; -} - -void ImportSpecification::setConnectionInformation(const ConnectionInformation& connectionInformation_) -{ - if (hasConnectionName()) - { - throw Error("import specification error: cannot set connection information, because there is already a connection name set"); - } - if (hasConnectionInformation()) - { - throw Error("import specification error: cannot set connection information more than once"); - } - connection_information = connectionInformation_; -} - - - -void ImportSpecification::addParameter(const std::string& key, const std::string& value) -{ - if (parameters.find(key) != parameters.end()) - { - std::stringstream sb; - sb << "import specification error: parameter with name '" << key << "', is set more than once"; - throw Error(sb.str()); - } - parameters[key] = value; -} - - -const std::string ImportSpecification::getConnectionName() const -{ - if (!hasConnectionName()) - { - throw Error("import specification error: cannot get connection name because it is not set"); - } - return connection_name; -} - -const ConnectionInformation ImportSpecification::getConnectionInformation() const -{ - if (!hasConnectionInformation()) - { - throw Error("import specification error: cannot get connection information because it is not set"); - } - return connection_information; -} - -const std::map& ImportSpecification::getParameters() const -{ - return parameters; -} - -////////////////////////////// - -ExportSpecification::ExportSpecification() - : isEmptySpec(true), - connection_name(""), - connection_information(), - parameters(), - truncate(false), - replace(false), - created_by(""), - source_column_names() -{ -} - -void ExportSpecification::accept(ScriptDTOSerializer& serializer) const -{ - serializer.visit(*this); -} - -bool ExportSpecification::isEmpty() const -{ - return isEmptySpec; -} - -bool ExportSpecification::hasConnectionName() const -{ - return !connection_name.empty(); -} - -bool ExportSpecification::hasConnectionInformation() const -{ - return !connection_information.hasData(); -} - -bool ExportSpecification::hasParameters() const -{ - return !parameters.empty(); -} - -bool ExportSpecification::hasTruncate() const -{ - return truncate; -} - -bool ExportSpecification::hasReplace() const -{ - return replace; -} - -bool ExportSpecification::hasCreatedBy() const -{ - return !created_by.empty(); -} - -void ExportSpecification::setConnectionName(const std::string& connectionName_) -{ - if (hasConnectionName()) - { - throw Error("export specification error: connection name is set more than once"); - } - if (hasConnectionInformation()) - { - throw Error("export specification error: cannot set connection name, because there is already connection information set"); - } - isEmptySpec = false; - connection_name = connectionName_; -} - -void ExportSpecification::setConnectionInformation(const ConnectionInformation& connectionInformation_) -{ - if (hasConnectionName()) - { - throw Error("export specification error: cannot set connection information, because there is already a connection name set"); - } - if (hasConnectionInformation()) - { - throw Error("export specification error: cannot set connection information more than once"); - } - isEmptySpec = false; - connection_information = connectionInformation_; -} - -void ExportSpecification::addParameter(const std::string& key, const std::string& value) -{ - if (parameters.find(key) != parameters.end()) - { - std::stringstream sb; - sb << "export specification error: parameter with name '" << key << "', is set more than once"; - throw Error(sb.str()); - } - isEmptySpec = false; - parameters[key] = value; -} - -void ExportSpecification::setTruncate(const bool truncate_) -{ - isEmptySpec = false; - truncate = truncate_; -} - -void ExportSpecification::setReplace(const bool replace_) -{ - isEmptySpec = false; - replace = replace_; -} - -void ExportSpecification::setCreatedBy(const std::string& createdBy_) -{ - if (!created_by.empty()) - { - throw Error("export specification error: cannot set created by more than once"); - } - isEmptySpec = false; - created_by = createdBy_; -} - -const std::string ExportSpecification::getConnectionName() const -{ - if (!hasConnectionName()) - { - throw Error("export specification error: cannot get connection name because it is not set"); - } - return connection_name; -} - -const ConnectionInformation ExportSpecification::getConnectionInformation() const -{ - if (!hasConnectionInformation()) - { - throw Error("export specification error: cannot get connection information because it is not set"); - } - return connection_information; -} - -const std::map& ExportSpecification::getParameters() const -{ - return parameters; -} - -const std::string ExportSpecification::getCreatedBy() const -{ - return created_by; -} - -void ExportSpecification::addSourceColumnName(const std::string& sourceColumnName_) -{ - isEmptySpec = false; - source_column_names.push_back(sourceColumnName_); -} - -const std::vector& ExportSpecification::getSourceColumnNames() const -{ - return source_column_names; -} - -} diff --git a/exaudfclient/base/exaudflib/swig/script_data_transfer_objects.h b/exaudfclient/base/exaudflib/swig/script_data_transfer_objects.h deleted file mode 100644 index 438acf0..0000000 --- a/exaudfclient/base/exaudflib/swig/script_data_transfer_objects.h +++ /dev/null @@ -1,242 +0,0 @@ -#ifndef SCRIPT_DATA_TRANSFER_OBJECTS_H -#define SCRIPT_DATA_TRANSFER_OBJECTS_H - -#include -#include -#include -#include -#include -#include - -namespace ExecutionGraph -{ - -class DTOError : public std::exception -{ -public: - explicit DTOError(const std::string& msg_) - : msg(msg_) - {} - virtual ~DTOError() throw() {} - virtual const char* what() const throw() - { - return msg.c_str(); - } - -protected: - std::string msg; -}; - - -class ScriptDTOSerializer -{ -public: - virtual void visit(const class ScriptDTO&) {std::abort();} - virtual void visit(const class ImportSpecification&) = 0; - virtual void visit(const class ExportSpecification&) = 0; - virtual void visit(const class ConnectionInformation&) = 0; - virtual void visit(const class StringDTO&) {std::abort();} // will be refactored. Only supported for Proto Serializer -}; - - -//! -//! -//! -//! - -class ScriptDTO -{ -public: - virtual void accept(ScriptDTOSerializer& serializer) const = 0; - virtual bool isEmpty() const = 0; -}; - -//! -//! -//! -//! - -class EmptyDTO : public ScriptDTO -{ -public: - EmptyDTO(); - - virtual void accept(ScriptDTOSerializer& serializer) const; - virtual bool isEmpty() const; -}; - - -//! -//! -//! -//! - -class ConnectionInformation : public ScriptDTO -{ -public: - class Error : public DTOError - { - public: - explicit Error(const std::string& msg) - : DTOError(msg) - {} - }; - - ConnectionInformation(); - - ConnectionInformation(const ConnectionInformation& other); - - ConnectionInformation(const std::string& kind, - const std::string& address, - const std::string& user, - const std::string& password); - - ConnectionInformation(const std::string& address, - const std::string& user, - const std::string& password); - - virtual void accept(ScriptDTOSerializer& serializer) const; - virtual bool isEmpty() const; - - const std::string getKind() const; - const std::string getAddress() const; - const std::string getUser() const; - const std::string getPassword() const; - - bool hasData() const; - -protected: - std::string kind; - std::string address; - std::string user; - std::string password; - -}; - - -class StringDTO : public ScriptDTO -{ -public: - StringDTO(); - StringDTO(const std::string& arg); - - virtual void accept(ScriptDTOSerializer& serializer) const; - virtual bool isEmpty() const; - - const std::string getArg() const; - -protected: - std::string arg; -}; - - -//! -//! -//! -//! -class ImportSpecification : public ScriptDTO -{ -private: - bool isEmptySpec; -public: - class Error : public DTOError - { - public: - explicit Error(const std::string& msg) - : DTOError(msg) - {} - }; - - virtual void accept(ScriptDTOSerializer& serializer) const; - virtual bool isEmpty() const; - - explicit ImportSpecification(); - explicit ImportSpecification(bool isSubselect__); - - void appendSubselectColumnName(const std::string& columnName); - void appendSubselectColumnType(const std::string& columnType); - void setConnectionName(const std::string& connectionName_); - void setConnectionInformation(const ConnectionInformation& connectionInformation_); - void addParameter(const std::string& key, const std::string& value); - - bool isSubselect() const; - bool hasSubselectColumnNames() const; - bool hasSubselectColumnTypes() const; - bool hasSubselectColumnSpecification() const; - bool hasConnectionName() const; - bool hasConnectionInformation() const; - bool hasParameters() const; - bool hasConsistentColumns() const; - bool isCompleteImportSubselectSpecification() const; - bool isCompleteImportIntoTargetTableSpecification() const; - - const std::vector& getSubselectColumnNames() const; - const std::vector& getSubselectColumnTypes() const; - const std::string getConnectionName() const; - const ConnectionInformation getConnectionInformation() const; - const std::map& getParameters() const; - -protected: - bool isSubselect_; - std::vector subselect_column_names; - std::vector subselect_column_types; - std::string connection_name; - ConnectionInformation connection_information; - std::map parameters; -}; - - -class ExportSpecification : public ScriptDTO -{ -public: - class Error : public DTOError - { - public: - explicit Error(const std::string& msg) - : DTOError(msg) - {} - }; - - virtual void accept(ScriptDTOSerializer& serializer) const; - virtual bool isEmpty() const; - - explicit ExportSpecification(); - - void setConnectionName(const std::string& connectionName_); - void setConnectionInformation(const ConnectionInformation& connectionInformation_); - void addParameter(const std::string& key, const std::string& value); - void setTruncate(const bool truncate_); - void setReplace(const bool replace_); - void setCreatedBy(const std::string& createdBy_); - void addSourceColumnName(const std::string& sourceColumnName_); - - bool hasConnectionName() const; - bool hasConnectionInformation() const; - bool hasParameters() const; - bool hasTruncate() const; - bool hasReplace() const; - bool hasCreatedBy() const; - - const std::string getConnectionName() const; - const ConnectionInformation getConnectionInformation() const; - const std::map& getParameters() const; - const std::string getCreatedBy() const; - const std::vector& getSourceColumnNames() const; - -private: - bool isEmptySpec; - -protected: - std::string connection_name; - ConnectionInformation connection_information; - std::map parameters; - bool truncate; - bool replace; - std::string created_by; - std::vector source_column_names; -}; - - -} - -#endif // SCRIPT_DATA_TRANSFER_OBJECTS_H diff --git a/exaudfclient/base/exaudflib/swig/script_data_transfer_objects_wrapper.cc b/exaudfclient/base/exaudflib/swig/script_data_transfer_objects_wrapper.cc deleted file mode 100644 index ff80750..0000000 --- a/exaudfclient/base/exaudflib/swig/script_data_transfer_objects_wrapper.cc +++ /dev/null @@ -1,103 +0,0 @@ -//#ifdef BUILDINSWIGDIR -//#include "scriptDTOWrapper.h" -//#else -#include "script_data_transfer_objects_wrapper.h" -//#endif - -#include - -namespace ExecutionGraph -{ - -ConnectionInformationWrapper::ConnectionInformationWrapper(const ConnectionInformation& connectionInformation_) - : connectionInformation(connectionInformation_) -{} - -char* ConnectionInformationWrapper::copyKind() const { - return strdup(connectionInformation.getKind().c_str()); -} -char* ConnectionInformationWrapper::copyAddress() const {return strdup(connectionInformation.getAddress().c_str());} -char* ConnectionInformationWrapper::copyUser() const {return strdup(connectionInformation.getUser().c_str());} -char* ConnectionInformationWrapper::copyPassword() const {return strdup(connectionInformation.getPassword().c_str());} - - -ImportSpecificationWrapper::ImportSpecificationWrapper(ImportSpecification* importSpecification_) - : importSpecification(importSpecification_) -{ - if (importSpecification != NULL) - { - // extract all the keys and values in some random but fixed order - for (std::map::const_iterator i = importSpecification->getParameters().begin(); - i != importSpecification->getParameters().end(); - ++i) - { - keys.push_back(i->first); - values.push_back(i->second); - } - } -} -bool ImportSpecificationWrapper::isSubselect() const {return importSpecification->isSubselect();} -size_t ImportSpecificationWrapper::numSubselectColumns() const {return importSpecification->getSubselectColumnNames().size();} -char* ImportSpecificationWrapper::copySubselectColumnName(size_t i) const {return ::strdup(importSpecification->getSubselectColumnNames().at(i).c_str());} -char* ImportSpecificationWrapper::copySubselectColumnType(size_t i) const {return ::strdup(importSpecification->getSubselectColumnTypes().at(i).c_str());} -bool ImportSpecificationWrapper::hasConnectionName() const {return importSpecification->hasConnectionName();} -bool ImportSpecificationWrapper::hasConnectionInformation() const {return importSpecification->hasConnectionInformation();} -char* ImportSpecificationWrapper::copyConnectionName() const {return ::strdup(importSpecification->getConnectionName().c_str());} -const ConnectionInformationWrapper ImportSpecificationWrapper::getConnectionInformation() const { - return ConnectionInformationWrapper(importSpecification->getConnectionInformation()); -} - -size_t ImportSpecificationWrapper::getNumberOfParameters() const {return keys.size();} -char* ImportSpecificationWrapper::copyKey(size_t pos) const {return ::strdup(keys.at(pos).c_str());} -char* ImportSpecificationWrapper::copyValue(size_t pos) const {return ::strdup(values.at(pos).c_str());} - - -ExportSpecificationWrapper::ExportSpecificationWrapper(ExportSpecification* exportSpecification_) - : exportSpecification(exportSpecification_) -{ - if (exportSpecification != NULL) - { - // extract all the keys and values in some random but fixed order - for (std::map::const_iterator i = exportSpecification->getParameters().begin(); - i != exportSpecification->getParameters().end(); - ++i) - { - keys.push_back(i->first); - values.push_back(i->second); - } - - for (std::vector::const_iterator i = exportSpecification->getSourceColumnNames().begin(); - i != exportSpecification->getSourceColumnNames().end(); i++) - { - columnNames.push_back(*i); - } - } -} -bool ExportSpecificationWrapper::hasConnectionName() const {return exportSpecification->hasConnectionName();} -bool ExportSpecificationWrapper::hasConnectionInformation() const {return exportSpecification->hasConnectionInformation();} -char* ExportSpecificationWrapper::copyConnectionName() const {return ::strdup(exportSpecification->getConnectionName().c_str());} -const ConnectionInformationWrapper ExportSpecificationWrapper::getConnectionInformation() const { - return ConnectionInformationWrapper(exportSpecification->getConnectionInformation()); -} -size_t ExportSpecificationWrapper::getNumberOfParameters() const {return keys.size();} -char* ExportSpecificationWrapper::copyKey(size_t pos) const {return ::strdup(keys.at(pos).c_str());} -char* ExportSpecificationWrapper::copyValue(size_t pos) const {return ::strdup(values.at(pos).c_str());} -bool ExportSpecificationWrapper::hasTruncate() const {return exportSpecification->hasTruncate();} -bool ExportSpecificationWrapper::hasReplace() const {return exportSpecification->hasReplace();} -bool ExportSpecificationWrapper::hasCreatedBy() const {return exportSpecification->hasCreatedBy();} -char* ExportSpecificationWrapper::copyCreatedBy() const { - if (exportSpecification->getCreatedBy().empty()) - return 0; - else - return ::strdup(exportSpecification->getCreatedBy().c_str()); -} - -size_t ExportSpecificationWrapper::numSourceColumns() const {return columnNames.size();} -char* ExportSpecificationWrapper::copySourceColumnName(size_t pos) const { - if (columnNames.at(pos).empty()) - return 0; - else - return ::strdup(columnNames.at(pos).c_str()); -} - -} diff --git a/exaudfclient/base/exaudflib/swig/script_data_transfer_objects_wrapper.h b/exaudfclient/base/exaudflib/swig/script_data_transfer_objects_wrapper.h deleted file mode 100644 index 7846d72..0000000 --- a/exaudfclient/base/exaudflib/swig/script_data_transfer_objects_wrapper.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef SCRIPT_DATA_TRANSFER_OBJECT_C_WRAPPER_H -#define SCRIPT_DATA_TRANSFER_OBJECT_C_WRAPPER_H - -#include "script_data_transfer_objects.h" - - -namespace ExecutionGraph -{ - -class ConnectionInformationWrapper -{ -public: - explicit ConnectionInformationWrapper(const ConnectionInformation& connectionInformation_); - char* copyKind() const; - char* copyAddress() const; - char* copyUser() const; - char* copyPassword() const; - -protected: - const ConnectionInformation connectionInformation; -}; - - -class ImportSpecificationWrapper -{ -public: - explicit ImportSpecificationWrapper(ExecutionGraph::ImportSpecification* importSpecification_); - bool isSubselect() const; - size_t numSubselectColumns() const; - char* copySubselectColumnName(size_t i) const; - char* copySubselectColumnType(size_t i) const; - bool hasConnectionName() const; - bool hasConnectionInformation() const; - char* copyConnectionName() const; - const ConnectionInformationWrapper getConnectionInformation() const; - size_t getNumberOfParameters() const; - char* copyKey(size_t pos) const; - char* copyValue(size_t pos) const; -protected: - ImportSpecification* importSpecification; - std::vector keys; - std::vector values; -}; - - -class ExportSpecificationWrapper -{ -public: - explicit ExportSpecificationWrapper(ExecutionGraph::ExportSpecification* exportSpecification_); - bool hasConnectionName() const; - bool hasConnectionInformation() const; - char* copyConnectionName() const; - const ConnectionInformationWrapper getConnectionInformation() const; - size_t getNumberOfParameters() const; - char* copyKey(size_t pos) const; - char* copyValue(size_t pos) const; - bool hasTruncate() const; - bool hasReplace() const; - bool hasCreatedBy() const; - char* copyCreatedBy() const; - size_t numSourceColumns() const; - char* copySourceColumnName(size_t i) const; -protected: - ExportSpecification* exportSpecification; - std::vector keys; - std::vector values; - std::vector columnNames; -}; - - - -} - -#endif // SCRIPT_DATA_TRANSFER_OBJECT_C_WRAPPER_H diff --git a/exaudfclient/base/exaudflib/swig/swig_common.cc b/exaudfclient/base/exaudflib/swig/swig_common.cc deleted file mode 100644 index ac2f69f..0000000 --- a/exaudfclient/base/exaudflib/swig/swig_common.cc +++ /dev/null @@ -1,2 +0,0 @@ -//Check that swig_common.h is self-contained -#include "exaudflib/swig/swig_common.h" \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/swig/swig_common.h b/exaudfclient/base/exaudflib/swig/swig_common.h deleted file mode 100644 index b61b0fc..0000000 --- a/exaudfclient/base/exaudflib/swig/swig_common.h +++ /dev/null @@ -1,186 +0,0 @@ -#ifndef SWIG_COMMON_H -#define SWIG_COMMON_H - -#include -#include -#include -#include - -namespace SWIGVMContainers { - -enum VMTYPE { - VM_UNSUPPORTED = 0, - VM_PYTHON = 1, - VM_SCHEME = 2, - VM_JAVASCRIPT = 3, - VM_R = 4, - VM_EXTERNAL = 5, - VM_PLUGIN_LANGUAGE = 7, - VM_BENCHMARK = 8 -}; - - -struct SWIGVMExceptionHandler -{ - SWIGVMExceptionHandler() { exthrowed = false; } - ~SWIGVMExceptionHandler() { } - void setException(const char* msg) { - exmsg = msg; exthrowed = true; - } - void setException(const std::string& msg) { - exmsg = msg; exthrowed = true; - } - std::string exmsg; - bool exthrowed; -}; - - -enum SWIGVM_datatype_e { - UNSUPPORTED = 0, - DOUBLE = 1, - INT32 = 2, - INT64 = 3, - NUMERIC = 4, - TIMESTAMP = 5, - DATE = 6, - STRING = 7, - BOOLEAN = 8, - INTERVALYM = 9, - INTERVALDS = 10, - GEOMETRY = 11 -}; - - -enum SWIGVM_itertype_e { - EXACTLY_ONCE = 1, - MULTIPLE = 2 -}; - -enum single_call_function_id_e { - SC_FN_NIL = 0, - SC_FN_DEFAULT_OUTPUT_COLUMNS = 1, - SC_FN_VIRTUAL_SCHEMA_ADAPTER_CALL = 2, - SC_FN_GENERATE_SQL_FOR_IMPORT_SPEC = 3, - SC_FN_GENERATE_SQL_FOR_EXPORT_SPEC = 4, -}; - -struct SWIGVM_columntype_t { - SWIGVM_datatype_e type; - std::string type_name; - unsigned int len; - unsigned int prec; - unsigned int scale; - SWIGVM_columntype_t(const SWIGVM_datatype_e t, const char *n, const unsigned int l, const unsigned int p, const unsigned int s): - type(t), type_name(n), len(l), prec(p), scale(s) { } - SWIGVM_columntype_t(const SWIGVM_datatype_e t, const char *n, const unsigned int l): type(t), type_name(n), len(l), prec(0), scale(0) { } - SWIGVM_columntype_t(const SWIGVM_datatype_e t, const char *n): type(t), type_name(n), len(0), prec(0), scale(0) { } - SWIGVM_columntype_t(): type(UNSUPPORTED), type_name("UNSUPPORTED"), len(0), prec(0), scale(0) { } -}; - - -struct SWIGVM_params_t { - uint64_t connection_id; - SWIGVMExceptionHandler *exch; - char *dbname; - char *dbversion; - char *script_name; - char *script_schema; - char *current_user; - char *current_schema; - char *scope_user; - char *script_code; - unsigned long long session_id; - unsigned long statement_id; - unsigned int node_count; - unsigned int node_id; - unsigned long long vm_id; - VMTYPE vm_type; - unsigned long long maximal_memory_limit; - std::vector *inp_names; - std::vector *inp_types; - SWIGVM_itertype_e inp_iter_type; - bool inp_force_finish; - std::vector *out_names; - std::vector *out_types; - SWIGVM_itertype_e out_iter_type; - bool m_allocate_params; - std::vector *is_emitted; - bool singleCallMode; - std::string pluginName; - std::string pluginURI; - std::string outputAddress; - SWIGVM_params_t(): - connection_id(0), exch(NULL), dbname(NULL), dbversion(NULL), script_name(NULL), script_schema(NULL), current_user(NULL), - current_schema(NULL), scope_user(NULL), script_code(NULL), - session_id(0), statement_id(0), node_count(0), node_id(0), vm_id(0), - vm_type(VM_UNSUPPORTED), maximal_memory_limit(0), - inp_names(NULL), inp_types(NULL), inp_iter_type(MULTIPLE), inp_force_finish(false), - out_names(NULL), out_types(NULL), out_iter_type(MULTIPLE), - m_allocate_params(false), - is_emitted(NULL), singleCallMode(false), pluginName(""), pluginURI(""), outputAddress("") - { } - SWIGVM_params_t(const bool allocate_params): - connection_id(0), exch(NULL), dbname(NULL), dbversion(NULL), script_name(NULL), script_schema(NULL), current_user(NULL), - current_schema(NULL), scope_user(NULL), script_code(NULL), - session_id(0), statement_id(0), node_count(0), node_id(0), vm_id(0), - vm_type(VM_UNSUPPORTED), maximal_memory_limit(0), - inp_names(allocate_params ? new std::vector() : NULL), - inp_types(allocate_params ? new std::vector() : NULL), - inp_iter_type(MULTIPLE), - inp_force_finish(false), - out_names(allocate_params ? new std::vector() : NULL), - out_types(allocate_params ? new std::vector() : NULL), - out_iter_type(MULTIPLE), - m_allocate_params(allocate_params), - is_emitted(allocate_params ? new std::vector() : NULL), - singleCallMode(false), pluginName(""), pluginURI(""), outputAddress("") - { } - SWIGVM_params_t(const SWIGVM_params_t &p): - connection_id(p.connection_id), - dbname(p.dbname), - dbversion(p.dbversion), - script_name(p.script_name), - script_schema(p.script_schema), - current_user(p.current_user), - current_schema(p.current_schema), - scope_user(p.scope_user), - script_code(p.script_code), - session_id(p.session_id), - statement_id(p.statement_id), - node_count(p.node_count), - node_id(p.node_id), - vm_id(p.vm_id), - vm_type(p.vm_type), - maximal_memory_limit(p.maximal_memory_limit), - inp_names(p.inp_names), - inp_types(p.inp_types), - inp_iter_type(p.inp_iter_type), - inp_force_finish(p.inp_force_finish), - out_names(p.out_names), - out_types(p.out_types), - out_iter_type(p.out_iter_type), - m_allocate_params(false), - is_emitted(p.is_emitted), - pluginName(p.pluginName), - pluginURI(p.pluginURI), - outputAddress(p.outputAddress) - { - if (p.m_allocate_params) - abort(); - } - ~SWIGVM_params_t() { - if (m_allocate_params) { - if (inp_names != NULL) { delete inp_names; inp_names = NULL; } - if (inp_types != NULL) { delete inp_types; inp_types = NULL; } - if (out_names != NULL) { delete out_names; out_names = NULL; } - if (out_types != NULL) { delete out_types; out_types = NULL; } - if (is_emitted != NULL) { delete is_emitted; is_emitted = NULL; } - } - } -}; - -extern __thread SWIGVM_params_t *SWIGVM_params; - -} //namespace SWIGVMContainers - -#endif //SWIG_COMMON_H diff --git a/exaudfclient/base/exaudflib/swig/swig_meta_data.cc b/exaudfclient/base/exaudflib/swig/swig_meta_data.cc deleted file mode 100644 index 1b1c6c7..0000000 --- a/exaudfclient/base/exaudflib/swig/swig_meta_data.cc +++ /dev/null @@ -1,2 +0,0 @@ -//Check that swig_meta_data.h is self-contained -#include "exaudflib/swig/swig_meta_data.h" \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/swig/swig_meta_data.h b/exaudfclient/base/exaudflib/swig/swig_meta_data.h deleted file mode 100644 index 4296208..0000000 --- a/exaudfclient/base/exaudflib/swig/swig_meta_data.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef SWIG_META_DATA_H -#define SWIG_META_DATA_H - -#include "exaudflib/load_dynamic.h" -#include "exaudflib/swig/swig_common.h" -#include "exaudflib/swig/script_data_transfer_objects_wrapper.h" -#include "exaudflib/udf_plugin_interface.h" - -namespace SWIGVMContainers { - -struct SWIGMetadataIf { - - virtual ~SWIGMetadataIf() {}; - virtual const char* databaseName() = 0; - virtual const char* databaseVersion() = 0; - virtual const char* scriptName() = 0; - virtual const char* scriptSchema() = 0; - virtual const char* currentUser() = 0; - virtual const char* scopeUser() = 0; - virtual const char* currentSchema() = 0; - virtual const char* scriptCode() = 0; - virtual const unsigned long long sessionID() = 0; - virtual const char *sessionID_S() = 0; - virtual const unsigned long statementID() = 0; - virtual const unsigned int nodeCount() = 0; - virtual const unsigned int nodeID() = 0; - virtual const unsigned long long vmID() = 0; - virtual const unsigned long long memoryLimit() = 0; - virtual const VMTYPE vmType() = 0; - virtual const char *vmID_S() = 0; - virtual const ExecutionGraph::ConnectionInformationWrapper* connectionInformation(const char* connection_name) = 0; - virtual const char* moduleContent(const char* name) = 0; - virtual const unsigned int inputColumnCount() = 0; - virtual const char *inputColumnName(unsigned int col) = 0; - virtual const SWIGVM_datatype_e inputColumnType(unsigned int col) = 0; - virtual const char *inputColumnTypeName(unsigned int col) = 0; - virtual const unsigned int inputColumnSize(unsigned int col) = 0; - virtual const unsigned int inputColumnPrecision(unsigned int col) = 0; - virtual const unsigned int inputColumnScale(unsigned int col) = 0; - virtual const SWIGVM_itertype_e inputType() = 0; - virtual const unsigned int outputColumnCount() = 0; - virtual const char *outputColumnName(unsigned int col) = 0; - virtual const SWIGVM_datatype_e outputColumnType(unsigned int col) = 0; - virtual const char *outputColumnTypeName(unsigned int col) = 0; - virtual const unsigned int outputColumnSize(unsigned int col) = 0; - virtual const unsigned int outputColumnPrecision(unsigned int col) = 0; - virtual const unsigned int outputColumnScale(unsigned int col) = 0; - virtual const SWIGVM_itertype_e outputType() = 0; - virtual const bool isEmittedColumn(unsigned int col) = 0; - virtual const char* checkException() = 0; - virtual const char* pluginLanguageName() = 0; - virtual const char* pluginURI() = 0; - virtual const char* outputAddress() = 0; -}; - - - -class SWIGMetadata : public SWIGMetadataIf { - SWIGMetadataIf* impl=nullptr; - typedef SWIGVMContainers::SWIGMetadataIf* (*CREATE_METADATA_FUN)(); - public: - SWIGMetadata() - { -#if !defined(UDF_PLUGIN_CLIENT) && !defined(USE_STATIC_SWIG) - CREATE_METADATA_FUN create = (CREATE_METADATA_FUN)load_dynamic("create_SWIGMetaData"); - impl = create(); -#else - impl = create_SWIGMetaData(); -#endif - } - - virtual ~SWIGMetadata() { - if (impl!=nullptr) { - delete impl; - } - } - virtual const char* databaseName() { return impl->databaseName(); } - virtual const char* databaseVersion() { return impl->databaseVersion(); } - virtual const char* scriptName() { return impl->scriptName(); } - virtual const char* scriptSchema() { return impl->scriptSchema(); } - virtual const char* currentUser() { return impl->currentUser(); } - virtual const char* scopeUser() { return impl->scopeUser(); } - virtual const char* currentSchema() {return impl->currentSchema();} - virtual const char* scriptCode() { return impl->scriptCode(); } - virtual const unsigned long long sessionID() { return impl->sessionID(); } - virtual const char *sessionID_S() { return impl->sessionID_S(); } - virtual const unsigned long statementID() { return impl->statementID(); } - virtual const unsigned int nodeCount() { return impl->nodeCount(); } - virtual const unsigned int nodeID() { return impl->nodeID(); } - virtual const unsigned long long vmID() { return impl->vmID(); } - virtual const unsigned long long memoryLimit() { return impl->memoryLimit(); } - virtual const VMTYPE vmType() { return impl->vmType(); } - virtual const char *vmID_S() { return impl->vmID_S(); } - virtual const ExecutionGraph::ConnectionInformationWrapper* connectionInformation(const char* connection_name){ - return impl->connectionInformation(connection_name); - } - virtual const char* moduleContent(const char* name) {return impl->moduleContent(name);} - virtual const unsigned int inputColumnCount() { return impl->inputColumnCount(); } - virtual const char *inputColumnName(unsigned int col) { return impl->inputColumnName(col);} - virtual const SWIGVM_datatype_e inputColumnType(unsigned int col) { return impl->inputColumnType(col);} - virtual const char *inputColumnTypeName(unsigned int col) { return impl->inputColumnTypeName(col); } - virtual const unsigned int inputColumnSize(unsigned int col) {return impl->inputColumnSize(col);} - virtual const unsigned int inputColumnPrecision(unsigned int col) { return impl->inputColumnPrecision(col); } - virtual const unsigned int inputColumnScale(unsigned int col) { return impl->inputColumnScale(col);} - virtual const SWIGVM_itertype_e inputType() { return impl->inputType();} - virtual const unsigned int outputColumnCount() { return impl->outputColumnCount(); } - virtual const char *outputColumnName(unsigned int col) { return impl->outputColumnName(col); } - virtual const SWIGVM_datatype_e outputColumnType(unsigned int col) { return impl->outputColumnType(col); } - virtual const char *outputColumnTypeName(unsigned int col) { return impl->outputColumnTypeName(col); } - virtual const unsigned int outputColumnSize(unsigned int col) { return impl->outputColumnSize(col); } - virtual const unsigned int outputColumnPrecision(unsigned int col) {return impl->outputColumnPrecision(col);} - virtual const unsigned int outputColumnScale(unsigned int col) {return impl->outputColumnScale(col);} - virtual const SWIGVM_itertype_e outputType() { return impl->outputType(); } - virtual const bool isEmittedColumn(unsigned int col){ return impl->isEmittedColumn(col);} - virtual const char* checkException() {return impl->checkException();} - virtual const char* pluginLanguageName() {return impl->pluginLanguageName();} - virtual const char* pluginURI() {return impl->pluginURI();} - virtual const char* outputAddress() {return impl->outputAddress();} -}; - -} // namespace SWIGVMContainers - -#endif //SWIG_META_DATA_H \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/swig/swig_result_handler.cc b/exaudfclient/base/exaudflib/swig/swig_result_handler.cc deleted file mode 100644 index 72365f4..0000000 --- a/exaudfclient/base/exaudflib/swig/swig_result_handler.cc +++ /dev/null @@ -1,2 +0,0 @@ -//Check that swig_result_handler.h is self-contained -#include "exaudflib/swig/swig_result_handler.h" \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/swig/swig_result_handler.h b/exaudfclient/base/exaudflib/swig/swig_result_handler.h deleted file mode 100644 index 5357b71..0000000 --- a/exaudfclient/base/exaudflib/swig/swig_result_handler.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef SWIG_RESULT_HANDLER_H -#define SWIG_RESULT_HANDLER_H - -#include -#include -#include -#include "exaudflib/load_dynamic.h" -#include "exaudflib/swig/swig_table_iterator.h" -#include "exaudflib/udf_plugin_interface.h" - -#define SWIG_MAX_VAR_DATASIZE 4000000 - -namespace SWIGVMContainers { - -class SWIGRAbstractResultHandler { -public: - virtual ~SWIGRAbstractResultHandler() {}; - virtual void reinitialize()=0; - virtual unsigned long rowsEmited()=0; - virtual void flush()=0; - virtual bool next()=0; - virtual void setDouble(unsigned int col, const double v)=0; - virtual void setString(unsigned int col, const char *v, size_t l)=0; - virtual void setInt32(unsigned int col, const int32_t v)=0; - virtual void setInt64(unsigned int col, const int64_t v)=0; - virtual void setNumeric(unsigned int col, const char *v)=0; - virtual void setTimestamp(unsigned int col, const char *v)=0; - virtual void setDate(unsigned int col, const char *v)=0; - virtual void setBoolean(unsigned int col, const bool v)=0; - virtual void setNull(unsigned int col)=0; - virtual const char* checkException()=0; -}; - - -class SWIGResultHandler { //: public SWIGRAbstractResultHandler { - SWIGRAbstractResultHandler* impl=nullptr; - typedef SWIGVMContainers::SWIGRAbstractResultHandler* (*CREATE_RESULTHANDLER_FUN)(SWIGVMContainers::SWIGTableIterator*); -public: - SWIGResultHandler(SWIGTableIterator* table_iterator) - { -#if !defined(UDF_PLUGIN_CLIENT) && !defined(USE_STATIC_SWIG) - CREATE_RESULTHANDLER_FUN creator = (CREATE_RESULTHANDLER_FUN)load_dynamic("create_SWIGResultHandler"); - impl = creator(table_iterator); -#else - impl = create_SWIGResultHandler(table_iterator); -#endif - } - - virtual ~SWIGResultHandler() { - if (impl!=nullptr) { - delete impl; - } - } - virtual void reinitialize() {impl->reinitialize(); } - virtual unsigned long rowsEmited() {return impl->rowsEmited();} - virtual void flush() {impl->flush();} - virtual bool next() {return impl->next();} - virtual void setDouble(unsigned int col, const double v) {impl->setDouble(col, v);} - virtual void setString(unsigned int col, const char *v, size_t l) {impl->setString(col,v,l);} - virtual void setInt32(unsigned int col, const int32_t v) {impl->setInt32(col,v);} - virtual void setInt64(unsigned int col, const int64_t v) {impl->setInt64(col,v);} - virtual void setNumeric(unsigned int col, const char *v) {impl->setNumeric(col,v);} - virtual void setTimestamp(unsigned int col, const char *v) {impl->setTimestamp(col,v);} - virtual void setDate(unsigned int col, const char *v) {impl->setDate(col,v);} - virtual void setBoolean(unsigned int col, const bool v) {impl->setBoolean(col,v);} - virtual void setNull(unsigned int col) {impl->setNull(col);} - const char* checkException() {return impl->checkException();} -}; - -} //namespace SWIGVMContainers - -#endif //SWIG_RESULT_HANDLER_H \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/swig/swig_table_iterator.cc b/exaudfclient/base/exaudflib/swig/swig_table_iterator.cc deleted file mode 100644 index 2e30676..0000000 --- a/exaudfclient/base/exaudflib/swig/swig_table_iterator.cc +++ /dev/null @@ -1,2 +0,0 @@ -//Check that swig_table_iterator.h is self-contained -#include "exaudflib/swig/swig_table_iterator.h" \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/swig/swig_table_iterator.h b/exaudfclient/base/exaudflib/swig/swig_table_iterator.h deleted file mode 100644 index 662c08c..0000000 --- a/exaudfclient/base/exaudflib/swig/swig_table_iterator.h +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef SWIG_TABLE_ITERATOR_H -#define SWIG_TABLE_ITERATOR_H - -#include -#include -#include -#include "exaudflib/load_dynamic.h" -#include "exaudflib/udf_plugin_interface.h" - -namespace SWIGVMContainers { - -class AbstractSWIGTableIterator { -public: - virtual ~AbstractSWIGTableIterator() {} - virtual void reinitialize()=0; - virtual bool next()=0; - virtual bool eot()=0; - virtual void reset()=0; - virtual unsigned long restBufferSize()=0; - virtual unsigned long rowsCompleted()=0; - virtual unsigned long rowsInGroup()=0; - virtual double getDouble(unsigned int col)=0; - virtual const char *getString(unsigned int col, size_t *length = NULL)=0; - virtual int32_t getInt32(unsigned int col)=0; - virtual int64_t getInt64(unsigned int col)=0; - virtual const char *getNumeric(unsigned int col)=0; - virtual const char *getTimestamp(unsigned int col)=0; - virtual const char *getDate(unsigned int col)=0; - virtual bool getBoolean(unsigned int col)=0; - virtual bool wasNull()=0; - virtual uint64_t get_current_row()=0; - virtual const char* checkException()=0; -}; - - - -class SWIGTableIterator { //: public AbstractSWIGTableIterator { - typedef SWIGVMContainers::AbstractSWIGTableIterator* (*CREATE_TABLEITERATOR_FUN)(); - - AbstractSWIGTableIterator* impl=nullptr; -public: - SWIGTableIterator() - { -#if !defined(UDF_PLUGIN_CLIENT) && !defined(USE_STATIC_SWIG) - CREATE_TABLEITERATOR_FUN creator = (CREATE_TABLEITERATOR_FUN)load_dynamic("create_SWIGTableIterator"); - impl = creator(); -#else - impl = create_SWIGTableIterator(); -#endif - } - - virtual ~SWIGTableIterator() { - if (impl!=nullptr) { - delete impl; - } - } - virtual void reinitialize() { impl->reinitialize();} - virtual bool next() { return impl->next(); } - virtual bool eot() { return impl->eot(); } - virtual void reset() { return impl->reset(); } - virtual unsigned long restBufferSize() { return impl->restBufferSize();} - virtual unsigned long rowsCompleted() { return impl->rowsCompleted();} - virtual unsigned long rowsInGroup() { return impl->rowsInGroup();} - virtual double getDouble(unsigned int col) { return impl->getDouble(col);} - virtual const char *getString(unsigned int col, size_t *length = NULL) {return impl->getString(col, length);} - virtual int32_t getInt32(unsigned int col) {return impl->getInt32(col);} - virtual int64_t getInt64(unsigned int col) {return impl->getInt64(col);} - virtual const char *getNumeric(unsigned int col) {return impl->getNumeric(col);} - virtual const char *getTimestamp(unsigned int col) {return impl->getTimestamp(col);} - virtual const char *getDate(unsigned int col) {return impl->getDate(col);} - virtual bool getBoolean(unsigned int col) {return impl->getBoolean(col);} - virtual bool wasNull() { return impl->wasNull();} - virtual uint64_t get_current_row() {return impl->get_current_row();} - const char* checkException() {return impl->checkException();} -}; - -} //namespace SWIGVMContainers - -#endif //SWIG_TABLE_ITERATOR_H \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/test/BUILD b/exaudfclient/base/exaudflib/test/BUILD deleted file mode 100644 index 1026d25..0000000 --- a/exaudfclient/base/exaudflib/test/BUILD +++ /dev/null @@ -1,8 +0,0 @@ -cc_test( - name = "exaudflib-test", - srcs = ["script_data_transfer_objects_test.cpp"], - deps = [ - "//exaudflib:script_data_transfer_objects", - "@googletest//:gtest_main", - ], -) \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/test/script_data_transfer_objects_test.cpp b/exaudfclient/base/exaudflib/test/script_data_transfer_objects_test.cpp deleted file mode 100644 index 6e146c3..0000000 --- a/exaudfclient/base/exaudflib/test/script_data_transfer_objects_test.cpp +++ /dev/null @@ -1,260 +0,0 @@ -#include "exaudflib/swig/script_data_transfer_objects.h" -#include - -using namespace ExecutionGraph; - - -class ImportSpecificationTest : public ::testing::Test { -protected: - virtual void SetUp() { - - } - virtual void TearDown() { - - } -}; - -TEST_F(ImportSpecificationTest, is_subselect) -{ - ImportSpecification is1(true); - ImportSpecification is2(false); - EXPECT_TRUE(is1.isSubselect()); - EXPECT_FALSE(is2.isSubselect()); -} - -TEST_F(ImportSpecificationTest, column_names_and_types_only_for_subselects) -{ - // append - ImportSpecification is1(false); - try { - is1.appendSubselectColumnName("col1"); - ADD_FAILURE(); - } catch (ImportSpecification::Error& e) - { - EXPECT_STREQ(e.what(), "import specification error: cannot add column name to non-subselect import specification"); - } - ImportSpecification is2(true); - try { - is2.appendSubselectColumnName("col1"); - } catch (ImportSpecification::Error& e) - { - ADD_FAILURE(); - } - ImportSpecification is3(false); - try { - is3.appendSubselectColumnType("type1"); - ADD_FAILURE(); - } catch (ImportSpecification::Error& e) - { - EXPECT_STREQ(e.what(), "import specification error: cannot add column type to non-subselect import specification"); - } - ImportSpecification is4(true); - try { - is4.appendSubselectColumnType("type1"); - } catch (ImportSpecification::Error& e) - { - ADD_FAILURE(); - } - // get - ImportSpecification is5(false); - try { - is5.getSubselectColumnNames(); - ADD_FAILURE(); - } catch (ImportSpecification::Error& e) - { - EXPECT_STREQ(e.what(), "import specification error: cannot get column names of non-subselect import specification"); - } - ImportSpecification is6(true); - try { - is6.getSubselectColumnNames(); - } catch (ImportSpecification::Error& e) - { - ADD_FAILURE(); - } - ImportSpecification is7(false); - try { - is7.getSubselectColumnTypes(); - ADD_FAILURE(); - } catch (ImportSpecification::Error& e) - { - EXPECT_STREQ(e.what(), "import specification error: cannot get column types of non-subselect import specification"); - } - ImportSpecification is8(true); - try { - is8.getSubselectColumnTypes(); - } catch (ImportSpecification::Error& e) - { - ADD_FAILURE(); - } -} - -TEST_F(ImportSpecificationTest, column_names_and_types) -{ - ImportSpecification is1(true); - EXPECT_FALSE(is1.hasSubselectColumnSpecification()); - is1.appendSubselectColumnName("col1"); - EXPECT_TRUE(is1.hasSubselectColumnSpecification()); - EXPECT_FALSE(is1.hasConsistentColumns()); - - is1.appendSubselectColumnType("type1"); - EXPECT_TRUE(is1.hasSubselectColumnSpecification()); - EXPECT_TRUE(is1.hasConsistentColumns()); - - is1.appendSubselectColumnName("col2"); - EXPECT_TRUE(is1.hasSubselectColumnSpecification()); - EXPECT_FALSE(is1.hasConsistentColumns()); - - is1.appendSubselectColumnType("type2"); - EXPECT_TRUE(is1.hasSubselectColumnSpecification()); - EXPECT_TRUE(is1.hasConsistentColumns()); - - is1.appendSubselectColumnName("col3"); - EXPECT_TRUE(is1.hasSubselectColumnSpecification()); - EXPECT_FALSE(is1.hasConsistentColumns()); - - is1.appendSubselectColumnType("type3"); - - EXPECT_TRUE(is1.hasSubselectColumnSpecification()); - EXPECT_TRUE(is1.hasConsistentColumns()); - EXPECT_EQ(is1.getSubselectColumnNames().size(), 3); - EXPECT_EQ(is1.getSubselectColumnTypes().size(), 3); - EXPECT_EQ(is1.getSubselectColumnNames()[0], "col1"); - EXPECT_EQ(is1.getSubselectColumnNames()[1], "col2"); - EXPECT_EQ(is1.getSubselectColumnNames()[2], "col3"); - EXPECT_EQ(is1.getSubselectColumnTypes()[0], "type1"); - EXPECT_EQ(is1.getSubselectColumnTypes()[1], "type2"); - EXPECT_EQ(is1.getSubselectColumnTypes()[2], "type3"); -} - -TEST_F(ImportSpecificationTest, connection_name_or_details) -{ - ImportSpecification is1(false); - is1.setConnectionName("some_connection"); - try { - is1.setConnectionInformation(ConnectionInformation("some_address","some_user","some_password")); - ADD_FAILURE(); - } catch(ImportSpecification::Error& e) { - EXPECT_STREQ(e.what(), "import specification error: cannot set connection information, because there is already a connection name set"); - } - - - // - - ImportSpecification is2(false); - is2.setConnectionInformation(ConnectionInformation("some_address","some_user","some_password")); - try { - is2.setConnectionName("some_connection"); - ADD_FAILURE(); - } catch(ImportSpecification::Error& e) { - EXPECT_STREQ(e.what(), "import specification error: cannot set connection name, because there is already connection information set"); - } -} - -TEST_F(ImportSpecificationTest, connection_dont_set_twice) -{ - ImportSpecification is1(false); - is1.setConnectionName("some_connection"); - try { - is1.setConnectionName("some_other_connection"); - ADD_FAILURE(); - } catch(ImportSpecification::Error& e) { - EXPECT_STREQ(e.what(), "import specification error: connection name is set more than once"); - } - ImportSpecification is2(false); - is2.setConnectionInformation(ConnectionInformation("some_address","some_user","some_password")); - try { - is2.setConnectionInformation(ConnectionInformation()); - ADD_FAILURE(); - } catch(ImportSpecification::Error& e) { - EXPECT_STREQ(e.what(), "import specification error: cannot set connection information more than once"); - } -} - - -TEST_F(ImportSpecificationTest, connection_info) -{ - ImportSpecification is1(false); - is1.setConnectionName("some_connection"); - EXPECT_EQ(is1.getConnectionName(), "some_connection"); - - ImportSpecification is2(false); - is2.setConnectionInformation(ConnectionInformation("some_address","some_user","some_password")); - EXPECT_EQ(is2.getConnectionInformation().getAddress(), "some_address"); - EXPECT_EQ(is2.getConnectionInformation().getUser(), "some_user"); - EXPECT_EQ(is2.getConnectionInformation().getPassword(), "some_password"); - EXPECT_EQ(is2.getConnectionInformation().getKind(), "password"); -} - - -TEST_F(ImportSpecificationTest, parameters) -{ - ImportSpecification is1(false); - EXPECT_FALSE(is1.hasParameters()); - is1.addParameter("key1","value1"); - EXPECT_TRUE(is1.hasParameters()); - std::map::const_iterator ps1 = is1.getParameters().begin(); - EXPECT_EQ(ps1->first, "key1"); - EXPECT_EQ(ps1->second, "value1"); - - is1.addParameter("key2","value2"); - EXPECT_TRUE(is1.hasParameters()); - std::map::const_iterator ps2 = is1.getParameters().begin(); - ++ps2; - EXPECT_EQ(ps2->first, "key2"); - EXPECT_EQ(ps2->second, "value2"); -} - -// -// -// -// -class ConnectionInformationTest : public ::testing::Test { -protected: - virtual void SetUp() { - - } - virtual void TearDown() { - - } -}; - -TEST_F(ConnectionInformationTest, address_user_password_construction) -{ - ConnectionInformation ci("some_address","some_user","some_password"); - EXPECT_EQ(ci.getKind(), "password"); - EXPECT_EQ(ci.getAddress(), "some_address"); - EXPECT_EQ(ci.getUser(), "some_user"); - EXPECT_EQ(ci.getPassword(), "some_password"); - EXPECT_FALSE(ci.hasData()); -} - -TEST_F(ConnectionInformationTest, kind_address_user_password_construction) -{ - ConnectionInformation ci("some_kind","some_address","some_user","some_password"); - EXPECT_EQ(ci.getKind(), "some_kind"); - EXPECT_EQ(ci.getAddress(), "some_address"); - EXPECT_EQ(ci.getUser(), "some_user"); - EXPECT_EQ(ci.getPassword(), "some_password"); - EXPECT_FALSE(ci.hasData()); -} - -TEST_F(ConnectionInformationTest, empty_construction) -{ - ConnectionInformation ci; - EXPECT_TRUE(ci.getKind().empty()); - EXPECT_TRUE(ci.getAddress().empty()); - EXPECT_TRUE(ci.getUser().empty()); - EXPECT_TRUE(ci.getPassword().empty()); - EXPECT_TRUE(ci.hasData()); -} - -TEST_F(ConnectionInformationTest, copy) -{ - ConnectionInformation ca("a","b","c","d"); - ConnectionInformation cb(ca); - EXPECT_EQ(ca.getKind(), cb.getKind()); - EXPECT_EQ(ca.getAddress(), cb.getAddress()); - EXPECT_EQ(ca.getUser(), cb.getUser()); - EXPECT_EQ(ca.getPassword(), cb.getPassword()); - EXPECT_EQ(ca.hasData(), cb.hasData()); -} diff --git a/exaudfclient/base/exaudflib/udf_plugin_interface.h b/exaudfclient/base/exaudflib/udf_plugin_interface.h deleted file mode 100644 index 8ff2b8b..0000000 --- a/exaudfclient/base/exaudflib/udf_plugin_interface.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef UDF_PLUGIN_INTERFACE_H -#define UDF_PLUGIN_INTERFACE_H - -#if defined(UDF_PLUGIN_CLIENT) || defined(USE_STATIC_SWIG) -namespace SWIGVMContainers { -class SWIGMetadataIf; -class AbstractSWIGTableIterator; -class SWIGRAbstractResultHandler; -class SWIGTableIterator; -} - -extern "C" { -SWIGVMContainers::SWIGMetadataIf* create_SWIGMetaData(); -SWIGVMContainers::AbstractSWIGTableIterator* create_SWIGTableIterator(); -SWIGVMContainers::SWIGRAbstractResultHandler* create_SWIGResultHandler(SWIGVMContainers::SWIGTableIterator* table_iterator); -} -#endif // UDF_PLUGIN_CLIENT - -#endif // UDF_PLUGIN_INTERFACE_H diff --git a/exaudfclient/base/exaudflib/vm/swig_vm.cc b/exaudfclient/base/exaudflib/vm/swig_vm.cc deleted file mode 100644 index 3e2d98f..0000000 --- a/exaudfclient/base/exaudflib/vm/swig_vm.cc +++ /dev/null @@ -1,2 +0,0 @@ -//Check that swig_vm.h is self-contained -#include "exaudflib/vm/swig_vm.h" \ No newline at end of file diff --git a/exaudfclient/base/exaudflib/vm/swig_vm.h b/exaudfclient/base/exaudflib/vm/swig_vm.h deleted file mode 100644 index 3f88c7a..0000000 --- a/exaudfclient/base/exaudflib/vm/swig_vm.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SWIGVM_H -#define SWIGVM_H - -#include -#include -#include -#include -#include "exaudflib/swig/swig_common.h" -#include "exaudflib/swig/script_data_transfer_objects_wrapper.h" - -namespace SWIGVMContainers { - -class SWIGVM { - public: - struct exception : public std::exception { - exception(const char *reason): m_reason(reason) { } - exception(const std::string& reason): m_reason(reason) { } - virtual ~exception() throw() { } - const char* what() const throw() { return m_reason.c_str(); } - private: - std::string m_reason; - }; - SWIGVM() { } - virtual ~SWIGVM() { } - virtual void shutdown() {}; - virtual void destroy() {}; - virtual bool run() = 0; - bool run_() { - try { - return run(); - } catch (SWIGVM::exception& ex) { - std::cerr << "SWGVM run_: caught: " << ex.what(); - std::lock_guard lck(exception_msg_mtx); - exception_msg = ex.what(); - return true; /* we are done */ - } - } - virtual bool useZmqSocketLocks() {return false;} - virtual const char* singleCall(single_call_function_id_e fn, const ExecutionGraph::ScriptDTO& args) = 0; - std::string exception_msg; - std::mutex exception_msg_mtx; - std::string calledUndefinedSingleCall; -}; - -} //namespace SWIGVMContainers - -#endif //SWIGVM_H \ No newline at end of file diff --git a/exaudfclient/base/load_dynamic.cc b/exaudfclient/base/load_dynamic.cc deleted file mode 100644 index f8d9ee4..0000000 --- a/exaudfclient/base/load_dynamic.cc +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef UDF_PLUGIN_CLIENT -#include //This is required for dynamic linking in new linker namespace, not required for plugins -#endif - -#include -#include "exaudflib/vm/swig_vm.h" - -static void* exaudflib_handle = nullptr; - -#ifndef UDF_PLUGIN_CLIENT - -void set_exaudflib_handle(void* handle) { - if(handle != nullptr) { - exaudflib_handle = handle; - } -} - -void* load_dynamic(const char* name) { - if(exaudflib_handle == nullptr) { - throw SWIGVMContainers::SWIGVM::exception("Error: exaudflib_handle is not set."); - } - void* res = dlsym(exaudflib_handle, name); - char* error; - if ((error = dlerror()) != nullptr) - { - std::stringstream sb; - sb << "Error when trying to load function '" << name << "': " << error; - throw SWIGVMContainers::SWIGVM::exception(sb.str().c_str()); - } - return res; -} -#endif - diff --git a/exaudfclient/base/protobuf_repository.bzl b/exaudfclient/base/protobuf_repository.bzl deleted file mode 100644 index eb98c85..0000000 --- a/exaudfclient/base/protobuf_repository.bzl +++ /dev/null @@ -1,32 +0,0 @@ -def _protobuf_local_repository_impl(repository_ctx): - if 'PROTOBUF_LIBRARY_PREFIX' in repository_ctx.os.environ: - library_prefix = repository_ctx.os.environ['PROTOBUF_LIBRARY_PREFIX'] - else: - fail("Environment Variable PROTOBUF_LIBRARY_PREFIX not found") - print("protobuf library prefix in environment specified; %s"%library_prefix) - - if 'PROTOBUF_INCLUDE_PREFIX' in repository_ctx.os.environ: - include_prefix = repository_ctx.os.environ['PROTOBUF_INCLUDE_PREFIX'] - else: - fail("Environment Variable PROTOBUF_INCLUDE_PREFIX not found") - print("protobuf include prefix in environment specified; %s"%include_prefix) - build_file_content = """ -load("@rules_cc//cc:defs.bzl", "cc_library") - -cc_library( - name = "protobuf", - srcs = glob(["protobuf/lib/**/libprotobuf*.so"]), - hdrs = glob(["protobuf/include/**"]), - includes = ["protobuf/include/"], - visibility = ["//visibility:public"] -)""" - print(build_file_content) - - repository_ctx.symlink(library_prefix, "./protobuf/lib") - repository_ctx.symlink(include_prefix, "./protobuf/include") - repository_ctx.file("BUILD", build_file_content) - -protobuf_local_repository = repository_rule( - implementation=_protobuf_local_repository_impl, - local = True, - environ = ["PROTOBUF_LIBRARY_PREFIX","PROTOBUF_BIN","PROTOBUF_INCLUDE_PREFIX"]) diff --git a/exaudfclient/base/python/exascript_python_wrap.py b/exaudfclient/base/python/exascript_python_wrap.py index d79fd1b..a49bbab 100644 --- a/exaudfclient/base/python/exascript_python_wrap.py +++ b/exaudfclient/base/python/exascript_python_wrap.py @@ -12,8 +12,9 @@ #print("sys.path append",path_to_pyexadataframe) sys.path.append(path_to_pyexadataframe) else: - #Path "external/exaudfclient_base+/" comes from external module "exaudfclient_base" - path_to_pyexadataframe="/exaudf/external/exaudfclient_base+/python/python3" + # The Python VM is built by this module, while the shared transport lives in + # the external exaudfclient_base module. + path_to_pyexadataframe="/exaudf/base/python/python3" #print("sys.path append",path_to_pyexadataframe) sys.path.append(path_to_pyexadataframe) @@ -357,4 +358,3 @@ def __pythonvm_wrapped_singleCall(fn,arg=None): "F-UDF-CL-SL-PYTHON-1118", "Exception during singleCall %s"%fn.__name__, sys.exc_info()) - diff --git a/exaudfclient/base/python/python3/BUILD b/exaudfclient/base/python/python3/BUILD index cb62d1a..d41d5eb 100644 --- a/exaudfclient/base/python/python3/BUILD +++ b/exaudfclient/base/python/python3/BUILD @@ -7,17 +7,17 @@ genrule( cmd = """ INCLUDES=`$$PYTHON3_PREFIX/bin/$$PYTHON3_VERSION-config --includes` mkdir -p build_exascript_python_tmp_cc/exaudflib - cp "$(location //exaudflib:swig/script_data_transfer_objects_wrapper.h)" "$(location //exaudflib:exascript.i)" build_exascript_python_tmp_cc/exaudflib + cp "$(location @exaudfclient_base//exaudflib:swig/script_data_transfer_objects_wrapper.h)" "$(location @exaudfclient_base//exaudflib:exascript.i)" build_exascript_python_tmp_cc/exaudflib cd build_exascript_python_tmp_cc swig -v $$INCLUDES -O -DEXTERNAL_PROCESS -Wall -c++ -python -py3 -addextern -module exascript_python -o "../$(location exascript_python.cc)" exaudflib/exascript.i #Run replace_swig_import_helper.py because the generated exascript_python.py is not compatible with Python 3.12 #TODO: Update Swig to a new version which produces code compatible with Python 3.12 cd .. - $$PYTHON3_PREFIX/bin/$$PYTHON3_VERSION "$(location //:replace_swig_import_helper.py)" "$(location exascript_python.py)" "$(location exascript_python.py)" + $$PYTHON3_PREFIX/bin/$$PYTHON3_VERSION "$(location @exaudfclient_base//:replace_swig_import_helper.py)" "$(location exascript_python.py)" "$(location exascript_python.py)" """, outs = ["exascript_python.cc", "exascript_python.py"], - srcs = ["//exaudflib:exascript.i","//exaudflib:swig/script_data_transfer_objects_wrapper.h"], - tools = ["//:replace_swig_import_helper.py"], + srcs = ["@exaudfclient_base//exaudflib:exascript.i","@exaudfclient_base//exaudflib:swig/script_data_transfer_objects_wrapper.h"], + tools = ["@exaudfclient_base//:replace_swig_import_helper.py"], ) genrule( @@ -31,39 +31,39 @@ genrule( genrule( name = "extend_exascript_python_preset_py", - cmd = 'bash $(location //python:extend_exascript_python_preset_py.sh) "$(location //python:exascript_python_preset_core.py)" "$(location exascript_python_preset.py)" "$$PYTHON3_PREFIX" "$$PYTHON3_VERSION" ""', + cmd = 'bash $(location //base/python:extend_exascript_python_preset_py.sh) "$(location //base/python:exascript_python_preset_core.py)" "$(location exascript_python_preset.py)" "$$PYTHON3_PREFIX" "$$PYTHON3_VERSION" ""', outs = ["exascript_python_preset.py"], - srcs = ["//python:exascript_python_preset_core.py"], - tools = ["//python:extend_exascript_python_preset_py.sh"] + srcs = ["//base/python:exascript_python_preset_core.py"], + tools = ["//base/python:extend_exascript_python_preset_py.sh"] ) genrule( name = "exascript_python_int", cmd = """ cp $(SRCS) . - $$PYTHON3_PREFIX/bin/$$PYTHON3_VERSION $(location //:build_integrated.py) "$(location exascript_python_int.h)" "exascript_python.py" "exascript_python_wrap.py" "exascript_python_preset.py" + $$PYTHON3_PREFIX/bin/$$PYTHON3_VERSION $(location @exaudfclient_base//:build_integrated.py) "$(location exascript_python_int.h)" "exascript_python.py" "exascript_python_wrap.py" "exascript_python_preset.py" """, outs = ["exascript_python_int.h"], - srcs = [":exascript_python_tmp_cc", "//python:exascript_python_wrap.py", ":extend_exascript_python_preset_py"], - tools = ["//:build_integrated.py"] + srcs = [":exascript_python_tmp_cc", "//base/python:exascript_python_wrap.py", ":extend_exascript_python_preset_py"], + tools = ["@exaudfclient_base//:build_integrated.py"] ) cc_library( name = "exascript_python", srcs = [":exascript_python_tmp_cc", ":exascript_python_tmp_h"], hdrs = [":exascript_python_tmp_h"], - deps = ["@python3//:python3","//exaudflib:exaudflib-deps","//exaudflib:header"], + deps = ["@python3//:python3","@exaudfclient_base//exaudflib:exaudflib-deps","@exaudfclient_base//exaudflib:header"], alwayslink=True, ) cc_library( name = "pythoncontainer", - srcs = ["//python:pythoncontainer.cc", ":dummy.h"], + srcs = ["//base/python:pythoncontainer.cc", ":dummy.h"], data = [":extend_exascript_python_preset_py"], hdrs = [":exascript_python_int", ":exascript_python_tmp_h"], include_prefix = ".", - deps = ["@python3//:python3",":exascript_python","//exaudflib:header", - "//utils:utils", "//python:pythoncontainer_header"], + deps = ["@python3//:python3",":exascript_python","@exaudfclient_base//exaudflib:header", + "@exaudfclient_base//utils:utils", "//base/python:pythoncontainer_header"], alwayslink=True, ) @@ -80,5 +80,5 @@ cc_binary( linkshared = 1, srcs = [":python_ext_dataframe.cc"], deps = ["@python3//:python3","@numpy//:numpy", - "//exaudflib:header", "//utils:utils"], + "@exaudfclient_base//exaudflib:header", "@exaudfclient_base//utils:utils"], ) diff --git a/exaudfclient/base/replace_swig_import_helper.py b/exaudfclient/base/replace_swig_import_helper.py deleted file mode 100644 index 3be049e..0000000 --- a/exaudfclient/base/replace_swig_import_helper.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -This script replaces the function `swig_import_helper` -in the automatically generated `exascript_python.py` with a simple import statement. -This is needed for Python 3.12, as the automatically generated code uses the library `imp` -which was removed in this Python version. -#TODO: Update Swig to a new version which produces code compatible with Python 3.12 -""" -import sys -from pathlib import Path - -old_function = """ - def swig_import_helper(): - from os.path import dirname - import imp - fp = None - try: - fp, pathname, description = imp.find_module('_exascript_python', [dirname(__file__)]) - except ImportError: - import _exascript_python - return _exascript_python - if fp is not None: - try: - _mod = imp.load_module('_exascript_python', fp, pathname, description) - finally: - fp.close() - return _mod - _exascript_python = swig_import_helper() - del swig_import_helper -""" - -new_function = """ - import _exascript_python -""" - -def replace_swig_import_helper(target, source): - source_code = Path(source).read_text() - - assert old_function in source_code - - new_source_code = source_code.replace(old_function, new_function) - - with open(target, 'w') as f: - f.write(new_source_code) - -if __name__ == "__main__": - if len(sys.argv) != 3: - print('Usage: replace_swig_import_helper.py target source') - sys.exit(1) - print(f"replacing function swig_import_helper() using source={sys.argv[2]} and target={sys.argv[1]}") - replace_swig_import_helper(sys.argv[1], sys.argv[2]) diff --git a/exaudfclient/base/streaming_container/BUILD b/exaudfclient/base/streaming_container/BUILD deleted file mode 100644 index 2107368..0000000 --- a/exaudfclient/base/streaming_container/BUILD +++ /dev/null @@ -1,10 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@rules_cc//cc:defs.bzl", "cc_library") - -cc_library( - name = "streamingcontainer", - srcs = ["streamingcontainer.cc","streamingcontainer.h"], - hdrs = ["streamingcontainer.h"], - deps = ["//exaudflib:exaudflib-deps","//exaudflib:header"] -) \ No newline at end of file diff --git a/exaudfclient/base/streaming_container/streamingcontainer.cc b/exaudfclient/base/streaming_container/streamingcontainer.cc deleted file mode 100644 index 57e4f9d..0000000 --- a/exaudfclient/base/streaming_container/streamingcontainer.cc +++ /dev/null @@ -1,344 +0,0 @@ -#include "streamingcontainer.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace SWIGVMContainers; -using namespace std; - - -bool mexec(const std::string& cmd_, std::string& result) { - char buffer[128]; - std::stringstream cmd; - cmd << "ulimit -v 500000; "; - cmd << cmd_ << " 2>&1"; - - FILE* pipe = popen(cmd.str().c_str(), "r"); - if (!pipe) { - result = "Cannot start command `" + cmd.str() + "`"; - return false; - } - while (!feof(pipe)) { - if (fgets(buffer, 128, pipe) != NULL) { - result += buffer; - } - } - int s = pclose(pipe); - if (s == -1) - { - return false; - } - if (WEXITSTATUS(s)) - { - return false; - } - return true; -} - - -StreamingVM::StreamingVM(bool checkOnly) - : meta(), inp(), outp(&inp), - csvPrinters{ -{UNSUPPORTED,[](ostream&, unsigned int) -> void { - throw SWIGVM::exception("Trying to serialize UNSUPPORTED datatype to CSV"); -}}, -{DOUBLE,[&](ostream&str, unsigned int col) {str << inp.getDouble(col);}}, -{INT32,[&](ostream&str, unsigned int col) {str << inp.getInt32(col);}}, -{INT64,[&](ostream&str, unsigned int col) {str << inp.getInt64(col);}}, -{NUMERIC,[&](ostream&str, unsigned int col) {str << inp.getNumeric(col);}}, -{TIMESTAMP,[&](ostream&str, unsigned int col) {str << inp.getTimestamp(col);}}, -{DATE,[&](ostream&str, unsigned int col) {str << inp.getDate(col);}}, -{STRING,[&](ostream&str, unsigned int col) { - //string o = inp.getString(col); - //std::cerr << "Sending Input: [" << o << "] for column " << col << std::endl; - str << inp.getString(col); -}}, -{BOOLEAN,[&](ostream&str, unsigned int col) {str << (inp.getBoolean(col)?"true":"false");}}, -{INTERVALYM,[&](ostream&, unsigned int) { - throw SWIGVM::exception("Trying to serialize INTERVALYM datatype to CSV"); -}}, -{INTERVALDS,[&](ostream&, unsigned int) { - throw SWIGVM::exception("Trying to serialize INTERVALDS datatype to CSV"); -}}, -{GEOMETRY,[&](ostream&, unsigned int) { - throw SWIGVM::exception("Trying to serialize GEOMETRY datatype to CSV"); -}} -}, - - -csvReaders{ - -// {UNSUPPORTED,[](ostream&, unsigned int) -> void { -// throw SWIGVM::exception("Trying to serialize UNSUPPORTED datatype to CSV"); -// }}, -// {DOUBLE,[&](ostream&str, unsigned int col) {str << inp.getDouble(col);}}, -// {INT32,[&](ostream&str, unsigned int col) {str << inp.getInt32(col);}}, -// {INT64,[&](ostream&str, unsigned int col) {str << inp.getInt64(col);}}, -// {NUMERIC,[&](ostream&str, unsigned int col) {str << inp.getNumeric(col);}}, -// {TIMESTAMP,[&](ostream&str, unsigned int col) {str << inp.getTimestamp(col);}}, -// {DATE,[&](ostream&str, unsigned int col) {str << inp.getDate(col);}}, - {STRING,[&](string&str, unsigned int col) { - std::cerr << "******* SETTING RESULT: [" << str << "] for column " << col << std::endl; - outp.setString(col,str.c_str(),-1);}} -// , -// {BOOLEAN,[&](ostream&str, unsigned int col) {str << (inp.getBoolean(col)?"true":"false");}}, -// {INTERVALYM,[&](ostream&, unsigned int) { -// throw SWIGVM::exception("Trying to serialize INTERVALYM datatype to CSV"); -// }}, -// {INTERVALDS,[&](ostream&, unsigned int) { -// throw SWIGVM::exception("Trying to serialize INTERVALDS datatype to CSV"); -// }}, -// {GEOMETRY,[&](ostream&, unsigned int) { -// throw SWIGVM::exception("Trying to serialize GEOMETRY datatype to CSV"); -// }} - -} - -{ - - - if (meta.inputType() != MULTIPLE - || meta.outputType() != MULTIPLE) - { - throw SWIGVM::exception("STREAMING language container only support SET-EMITS UDFs"); - } - - - ofstream f("/tmp/program"); - f << meta.scriptCode(); - f.close(); - - string res; - if (!mexec("chmod +x /tmp/program",res)) { - std::stringstream msg; - msg << "Error when making script code executable: " << res; - throw SWIGVM::exception(msg.str().c_str()); - } - - readBuffer.reserve(1024 * 1024 * 2); -} - -void StreamingVM::shutdown() -{ - -} - -void StreamingVM::inputToCSV(ostream&str) -{ - if (meta.inputColumnCount()>0) { - csvPrinters[meta.inputColumnType(0)](str,0); - for (unsigned int col = 1; col 0) { - outp.next(); // make room for the data unless it is the first emitted row - } - csvReaders[meta.outputColumnType(0)](readBuffer,0); - for (unsigned int col = 1; col outFilebuf(pproc_in[PIPE_WRITE_END], std::ios::out); - ostream os(&outFilebuf); - - __gnu_cxx::stdio_filebuf inFilebuf(pproc_out[PIPE_READ_END], std::ios::in); - istream is(&inFilebuf); - - __gnu_cxx::stdio_filebuf errorFilebuf(pproc_error[PIPE_READ_END], std::ios::in); - istream es(&errorFilebuf); - - thread t1([&]() - { - try { - do { - inputToCSV(os); - } while (inp.next()); - os.flush(); - close(pproc_in[PIPE_WRITE_END]); - } catch (std::exception& err) { - lock_guard lock(exception_msg_mtx); - exception_msg = err.what(); - } - }); - - thread t2([&]() - { - try { - while (!is.eof()) { - if (!CSVToOutput(is)) { - break; - } - } - outp.flush(); - } catch (std::exception& err) { - lock_guard lock(exception_msg_mtx); - exception_msg = err.what(); - } - }); - - t1.join(); - t2.join(); - - - close(pproc_out[PIPE_READ_END]); - - if (exception_msg.size() == 0) { - readBuffer.clear(); // error messages from the subprocess? - while (readBuffer.size()<1000) { - int current = es.get(); - if (current == string::traits_type::eof()) { - break; - } - readBuffer += current; - } - - if (!es.eof() && readBuffer.size()>0) { - readBuffer += "..."; - } - } - close(pproc_error[PIPE_READ_END]); - if (waitpid(pproc_pid,NULL,0) < 0) { - perror("waitpid"); - exit(EXIT_FAILURE); - } - - if (exception_msg.size() > 0) { - throw SWIGVM::exception(exception_msg.c_str()); - } - - if (readBuffer.size()>0) { - string error_msg = "Error output during script execution:\n"+readBuffer; - throw SWIGVM::exception(error_msg.c_str()); - } - - - } catch (std::exception& ex) { - lock_guard lock(exception_msg_mtx); - exception_msg = ex.what(); - } - return true; // done -} - -const char* StreamingVM::singleCall(single_call_function_id_e fn, const ExecutionGraph::ScriptDTO& args) -{ - throw SWIGVM::exception("singleCall not supported for the STREAMING language container"); -} \ No newline at end of file diff --git a/exaudfclient/base/streaming_container/streamingcontainer.h b/exaudfclient/base/streaming_container/streamingcontainer.h deleted file mode 100644 index b45faac..0000000 --- a/exaudfclient/base/streaming_container/streamingcontainer.h +++ /dev/null @@ -1,30 +0,0 @@ - -using namespace SWIGVMContainers; -using namespace std; - - -class StreamingVM: public SWIGVM { - public: - struct exception: SWIGVM::exception { - exception(const char *reason): SWIGVM::exception(reason) { } - virtual ~exception() throw() { } - }; - StreamingVM(bool checkOnly); - virtual ~StreamingVM() {}; - virtual void shutdown(); - virtual bool run(); - virtual const char* singleCall(single_call_function_id_e fn, const ExecutionGraph::ScriptDTO& args); - virtual bool useZmqSocketLocks() {return true;} - private: - SWIGMetadata meta; - SWIGTableIterator inp; - SWIGResultHandler outp; - void importScripts(); - map > csvPrinters; - map > csvReaders; - void inputToCSV(ostream&str); - bool CSVToOutput(istream&str); - string readBuffer; - // returns true if a an entry could be read - bool readCSVValue(istream&str, unsigned int column); -}; diff --git a/exaudfclient/base/swig_factory/BUILD b/exaudfclient/base/swig_factory/BUILD deleted file mode 100644 index 19e5f85..0000000 --- a/exaudfclient/base/swig_factory/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -load("@rules_cc//cc:defs.bzl", "cc_library") - -cc_library( - name = "swig_factory_if", - hdrs = [":swig_factory.h"], -) - - -cc_library( - name = "swig_factory", - hdrs = [":swig_factory.h", ":swig_factory_impl.h"], - srcs = [":swig_factory_impl.cc"], - deps = ["//exaudflib:header"], -) diff --git a/exaudfclient/base/swig_factory/swig_factory.h b/exaudfclient/base/swig_factory/swig_factory.h deleted file mode 100644 index 48f93c1..0000000 --- a/exaudfclient/base/swig_factory/swig_factory.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef SWIG_FACTORY_H -#define SWIG_FACTORY_H 1 - -namespace SWIGVMContainers { - -struct SWIGMetadataIf; - -struct SwigFactory { - virtual ~SwigFactory() {}; - - virtual SWIGMetadataIf* makeSwigMetadata() = 0; - -}; - - -} // namespace SWIGVMContainer - -#endif //SWIG_FACTORY_H \ No newline at end of file diff --git a/exaudfclient/base/swig_factory/swig_factory_impl.cc b/exaudfclient/base/swig_factory/swig_factory_impl.cc deleted file mode 100644 index b4b3207..0000000 --- a/exaudfclient/base/swig_factory/swig_factory_impl.cc +++ /dev/null @@ -1,19 +0,0 @@ -#include "swig_factory/swig_factory_impl.h" -#include "exaudflib/load_dynamic.h" -#include "exaudflib/swig/swig_common.h" - -namespace SWIGVMContainers { - -SWIGMetadataIf* SwigFactoryImpl::makeSwigMetadata() { - SWIGMetadataIf* impl=nullptr; - typedef SWIGVMContainers::SWIGMetadataIf* (*CREATE_METADATA_FUN)(); -#ifndef UDF_PLUGIN_CLIENT - CREATE_METADATA_FUN create = (CREATE_METADATA_FUN)load_dynamic("create_SWIGMetaData"); - impl = create(); -#else - impl = create_SWIGMetaData(); -#endif - return impl; -} - -} //namespace SWIGVMContainers diff --git a/exaudfclient/base/swig_factory/swig_factory_impl.h b/exaudfclient/base/swig_factory/swig_factory_impl.h deleted file mode 100644 index 5bfbb00..0000000 --- a/exaudfclient/base/swig_factory/swig_factory_impl.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef SWIG_FACTORY_IMPL_H -#define SWIG_FACTORY_IMPL_H 1 - -#include "swig_factory/swig_factory.h" - -namespace SWIGVMContainers { - -struct SwigFactoryImpl : public SwigFactory { - - virtual SWIGMetadataIf* makeSwigMetadata() override; - -}; - -} // namespace SWIGVMContainers - - -#endif //namespace SWIG_FACTORY_IMPL_H \ No newline at end of file diff --git a/exaudfclient/base/utils/BUILD b/exaudfclient/base/utils/BUILD deleted file mode 100644 index ddf4e03..0000000 --- a/exaudfclient/base/utils/BUILD +++ /dev/null @@ -1,12 +0,0 @@ - -package(default_visibility = ["//visibility:public"]) - -load("@rules_cc//cc:defs.bzl", "cc_library") - -cc_library( - name = "utils", - hdrs = [ - "debug_message.h", "exceptions.h" - ], -) - diff --git a/exaudfclient/base/utils/debug_message.h b/exaudfclient/base/utils/debug_message.h deleted file mode 100644 index e74d892..0000000 --- a/exaudfclient/base/utils/debug_message.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef DEBUG_MESSAGE_H -#define DEBUG_MESSAGE_H - -#define PRINT_EXCEPTION( os, error_code, ex ) \ - (os) << (error_code) << ":" << " Caught Exception: " << (ex.what()) << std::endl - -#define PRINT_ERROR_MESSAGE( os, error_code, error_message ) \ - (os) << (error_code) << ":" << error_message << std::endl - -#ifndef NDEBUG - -#define DBG_EXCEPTION( os, ex ) \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") in " << __func__ << " " \ - << "EXCEPTION: " << #ex << " = [" << (ex.what()) << "]" << std::endl - -#define DBGVAR( os, var ) \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") in " << __func__ << " " \ - << "VAR: " << #var << " = [" << (var) << "]" << std::endl - -#define DBGMSG( os, msg ) \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") in " << __func__ << " " \ - << (msg) << std::endl - -#define DBG_STREAM_MSG( os, msg ) \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") in " << __func__ << " " \ - << msg << std::endl - - -#define DBG_FUNC_BEGIN( os ) \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") BEGIN FUNC: " \ - << __func__ << std::endl - -#define DBG_FUNC_END( os ) \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") END FUNC: " \ - << __func__ << std::endl - -#define DBG_FUNC_CALL( os, call ) \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") " \ - << "CALL BEGIN: " << #call << std::endl; \ - call; \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") " \ - << "CALL END: " << #call << std::endl - -#define DBG_COND_FUNC_CALL( os, call ) \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") " \ - << "CALL BEGIN: " << #call << std::endl; \ - call; \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") " \ - << "CALL END: " << #call << std::endl - -#else - -#define DBG_EXCEPTION( os, ex ) - -#define DBGVAR( os, var ) - -#define DBGMSG( os, msg ) - -#define DBG_STREAM_MSG( os, msg ) - -#define DBG_FUNC_BEGIN( os ) - -#define DBG_FUNC_END( os ) - -#define DBG_FUNC_CALL( os, call ) call - -#define DBG_COND_FUNC_CALL( os, call ) - -#endif - -#endif diff --git a/exaudfclient/base/utils/exceptions.h b/exaudfclient/base/utils/exceptions.h deleted file mode 100644 index ec37a87..0000000 --- a/exaudfclient/base/utils/exceptions.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef UTILS_EXCEPTION_H -#define UTILS_EXCEPTION_H - -#include -#include - -namespace Utils { - -template -inline void rethrow(const TException& sourceException, const std::string_view& prefix) { - throw TException(std::string(prefix) + " " + sourceException.what()); -} - -} //namespace Utils - -#endif //UTILS_EXCEPTION_H \ No newline at end of file diff --git a/exaudfclient/base/variables.bzl b/exaudfclient/base/variables.bzl deleted file mode 100644 index a7ebd5d..0000000 --- a/exaudfclient/base/variables.bzl +++ /dev/null @@ -1,17 +0,0 @@ -BENCHMARK_VM_ENABLED_DEFINE=select({ - "//:benchmark": ["ENABLE_BENCHMARK_VM"], - "//conditions:default": [] - }) -STREAMING_VM_ENABLED_DEFINE=select({ - "//:bash": ["ENABLE_STREAMING_VM"], - "//conditions:default": [] - }) -PYTHON_VM_ENABLED_DEFINE=select({ - "//:python": ["ENABLE_PYTHON_VM"], - "//conditions:default": [] - }) -PLUGIN_CLIENT_ENABLED_DEFINE=select({ - "//:plugin_client": ["UDF_PLUGIN_CLIENT"], - "//conditions:default": [] - }) -VM_ENABLED_DEFINES=BENCHMARK_VM_ENABLED_DEFINE+PYTHON_VM_ENABLED_DEFINE+STREAMING_VM_ENABLED_DEFINE+PLUGIN_CLIENT_ENABLED_DEFINE diff --git a/exaudfclient/base/zmq_repository.bzl b/exaudfclient/base/zmq_repository.bzl deleted file mode 100644 index dbab068..0000000 --- a/exaudfclient/base/zmq_repository.bzl +++ /dev/null @@ -1,32 +0,0 @@ -def _zmq_local_repository_impl(repository_ctx): - if 'ZMQ_LIBRARY_PREFIX' in repository_ctx.os.environ: - library_prefix = repository_ctx.os.environ['ZMQ_LIBRARY_PREFIX'] - else: - fail("Environment Variable ZMQ_LIBRARY_PREFIX not found") - print("zmq library prefix in environment specified; %s"%library_prefix) - - if 'ZMQ_INCLUDE_PREFIX' in repository_ctx.os.environ: - include_prefix = repository_ctx.os.environ['ZMQ_INCLUDE_PREFIX'] - else: - fail("Environment Variable ZMQ_INCLUDE_PREFIX not found") - print("zmq include prefix in environment specified; %s"%include_prefix) - build_file_content = """ -load("@rules_cc//cc:defs.bzl", "cc_library") - -cc_library( - name = "zmq", - srcs = glob(["zmq/lib/**/libzmq.so"]), - hdrs = glob(["zmq/include/zmq*"]), - includes = ["zmq/include/"], - visibility = ["//visibility:public"] -)""" - print(build_file_content) - - repository_ctx.symlink(library_prefix, "./zmq/lib") - repository_ctx.symlink(include_prefix, "./zmq/include") - repository_ctx.file("BUILD", build_file_content) - -zmq_local_repository = repository_rule( - implementation=_zmq_local_repository_impl, - local = True, - environ = ["ZMQ_LIBRARY_PREFIX","ZMQ_INCLUDE_PREFIX"]) diff --git a/exaudfclient/base/exaudflib/zmqcontainer.proto b/exaudfclient/base/zmqcontainer.proto similarity index 98% rename from exaudfclient/base/exaudflib/zmqcontainer.proto rename to exaudfclient/base/zmqcontainer.proto index 5cbca1d..00ef7a5 100644 --- a/exaudfclient/base/exaudflib/zmqcontainer.proto +++ b/exaudfclient/base/zmqcontainer.proto @@ -83,6 +83,7 @@ enum exascript_vmtype { PB_VM_JAVASCRIPT = 3; PB_VM_R = 4; PB_VM_EXTERNAL = 5; + PB_VM_JAVA = 6; PM_VM_PLUGIN_LANGUAGE = 7; } */ @@ -257,6 +258,3 @@ message exascript_response { optional exascript_close close = 6; optional exascript_import_rep import = 7; optional exascript_next_data_rep next = 8; - optional exascript_ping ping = 9; - optional exascript_single_call_rep call = 10; -} diff --git a/exaudfclient/docs/diagrams/CTPGParserHandler.drawio.png b/exaudfclient/docs/diagrams/CTPGParserHandler.drawio.png deleted file mode 100644 index 1b4836e327459e60a36a2b7103014c797b576ad7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 101619 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 n)b<(c^qTZBg=vMJ;|J4C(L&!!Hyc1ft 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 diff --git a/exaudfclient/docs/diagrams/LegacyParserHandler.drawio.png b/exaudfclient/docs/diagrams/LegacyParserHandler.drawio.png deleted file mode 100644 index 0907f6dc89ed51d357e3bb3fc9fe5b7144a70265..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 91552 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 diff --git a/exaudfclient/docs/diagrams/OveralScriptOptionalsBuildingBlocks.drawio.png b/exaudfclient/docs/diagrams/OveralScriptOptionalsBuildingBlocks.drawio.png deleted file mode 100644 index b834931d9c993e3dbc303cc8d6a61eb923150297..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26488 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 Si2z=u!{F)a=d#Wzp$Py!X|cip diff --git a/exaudfclient/docs/diagrams/ScriptOptionsExtractorInterface.drawio.png b/exaudfclient/docs/diagrams/ScriptOptionsExtractorInterface.drawio.png deleted file mode 100644 index 6583634b580d336073de4b19146b1c6d0d1bad42..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13749 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 ZbOxQXM}Djm{68!L4HX^bBE_5j{|Cau=PUpK diff --git a/exaudfclient/docs/diagrams/ScriptOptionsParserHandlerSequence.drawio.png b/exaudfclient/docs/diagrams/ScriptOptionsParserHandlerSequence.drawio.png deleted file mode 100644 index dbaac3fd60a5e12bad1851334c8fe86813bd5cd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41919 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%0DgI|{HevZrC-u?X7-}o# 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 (jK6{Fa4*kGbb* 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 jU>rbS?=}B!?Y==?%2t0F1E4f-W diff --git a/exaudfclient/docs/exaudfclient.drawio b/exaudfclient/docs/exaudfclient.drawio deleted file mode 100644 index d686c21..0000000 --- a/exaudfclient/docs/exaudfclient.drawio +++ /dev/null @@ -1 +0,0 @@ -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 \ No newline at end of file diff --git a/exaudfclient/docs/exaudfclient.png b/exaudfclient/docs/exaudfclient.png deleted file mode 100644 index 701fa73c2e792064f4951b4a0d30a17b147235db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178663 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

$#V~vdolv?epdqa z7MAO_1ikE)8wcPy#dd;b9GU-w{o(|ggh#96qU8>gQhE{qto5m@*^*!vppl<1uPocY zw>&HyWY1*4T(AURWKSYj1~$r!Mt*{OT&nM4{Au^d&q^&nyz;VN*LJOOcUI- zoFFZj zzAodTQdYVKd+Uj<%r(q0G~)9_#7AkO&gUn+w=Tk(rNf+^$5J1&!WGo7*@}j^geyPh z=CT{Rmj;#lVzAL-2-6D-A@JH}U{NQ$`Y!Ou0Dmozp#Qc2L@D;>7n~+)?Qrt)e_A(z zjJPAn&oT!hnC)_Lu8jeQBk?;}VC=E5v85xfOA_0zz|9RWm=%GQ$q;ZU$a@4*l}M6| z20`eE52-FqKk+w2-&nr9FxU4RA9sFKE>7(r*uX#Fjqwy8QI)_E?&4n%eRn~pn3jl6 zLOvrhh=ffGk&SYuk-qOeV5g<4Gb!cz>&mE*T?mK=+L&q$nd_I%G!r&QkqgIG^9Huk z>(-95Y6#Tb_I%c17@jg?HMLv!o53@3k=3|TWOT%TLlwY zs-*@oQ;{=S{)*{-rbI-m@Zy>sPq!OwrNcPw+ckX=)(=D33c84+Yn0Waf^Oy_kB_iJ z>b~P=2O42N%__%_bHT;HG+3)M_=?{Ud-rkJDvUj4P|*ZQgd@rtW!9arDu|XnQ_$*@ zi))?%w}=y{_HLpLAU$aNZg0Ro%c<$&=Px~LAntAg8(!fqAb-Z>?c=in{34yu1yuxd z4G(3s-Ph~LZ`(x($}bnwr|001Yk~H6=MQlN+wX$~y5F+GFrubS{-w^B$S}G+Fnj+5 z=tALHvpYax)~$3-MM#UBlNO(B8E}Hm}(HhixSK;C0D%m*RQdUVi z@s%&3pV~bO`VXAG+g01w)pO$dry-b`?z-2`+_Tvw>G@j&uXN`>lT^+#l5iuL%TG`$ zU+l#UgWCh}_ZG_(nmDI8NM*J^JN+e*n`L#PHln!hV(o`q{>t-8sKGbd6w zsL9-5fZ;y4(^&qwKUT=hK*Dn$7nU^SBa?f1O}76DnY~-%LfTe$i!cV4_TI0_T755= z=AX~Ba-XU5Tbml*tTSEzaO2Bu`k0Sg<&!wMP=STy^b)^>u|czdUKj2eMnrkR@jFuG zk|)7|B`bfJSnz%RrzsO*-u-G0H$3r1-+J-4GKDDw6T~f=ExLgOto zo6mj?6;ct>Nfk(0EehnTj2402V9aLEF_;{NO;;pzIzAlThVi(9JnHUE@DE`mT)GId zZrY^2G{9n7qulMRMs;MjRX;CaREt3Z#gQuaX3Fcvnm6yjFr=NSPf?3c$qKlYk6=|k zOEpPtZrygc=w+X}xZa~whPCpD`)dT;3+CtdG<=qKk)1;?Cxq=g3CM3i2!18{hvqxr zT@@;WMgNKgDGK_UqzZhX9ETM-zJG1;k@O%Mg&8fr?g?5H-&Xh=YC`rDpHZjqT5N0E zj+I;tQoYjB?fRDKcIC~t4jKq%={@Mh8b9MR>DJyoO-n#8q?Ii+V8Tqsb>m$8GKsCjv7wfL=WPbHqeyi?CH6L+C#SV&qmiJ~`Y6QztxT->&yL+kC zK0k$^(T+-;T##?On_cpAR!u&NjI?HSuO$&*m*?Tajv*3monpzm4OdWy8Wdg0=?lkR-KeX1#;Dbsdqt0ycupD5!2XzgLoZ z`J~|IUYaNy^Z3|u{;fYnVB=Kd^XX7~t?19L?Gy0a%=Sty}g@k(3*%s=ml>B)pV zWu+n-2E_Ds#?tZ%tEy3279!IT~_jNL&;|=F(Xwf z{h{P;MHxR!%>s$LH$S8xTwvQFe79F2(^a<*>%%&o$#9~(*3~5zmP%aAA=$IGmVeHE zref$pVlOdo(O z$%v4GR@r1Ypd2tMi=-2xMGzfDE?!0;kpll2?MOJCpgF8xdr1dMTvWIs(sg^`S$98q zbE0=1e|eN;I&R3GV%s)7i0XNz?{kGy=L#v_o#uWPb)AvJI^o|6`7MQ|p2O@TjWxx0 zt6y((=q&{5m72ZzJ^9WqMjDCyyscOWn=avrTwpk#DfObc$Cqy4?S4X*3+d_ocZ`ME zIshKNob)QEdr!q=s60*murRAWv-i(9rGyAgKl$fFAbMWW#POBlTtEpLCdi6Sxc@Fk zKK~&}PdpIBbQG&2sf4>K0?R^O{*H09jy}IP>nC(^*z%wqHkR{xD-mVu(gRBc?-<$A z~Klp}e~@jTH-k)4)L?p|6bwzlNF$DkiDx-X;q^l0)bi#+V7$GbH!` zT?$|tCc2K=>{|KVQ`)U$g%=#-HF$(&7-Rb=G^;?jO6sbIptd(;UyiqB6OaFO93AJ^K5Hv22l?)9CCd_Nm(y-j7 zA8*NI+8k>Ay&|zrEf_Tho8kKw?$)_^!cpg8jJSUfe2+rn1W3 z3uj5if-`(YlE+aSB2F};#SdR-*W5RoU2fD*{Y46hhq?i3 zIn=poGFepRNSlpwf8aZ&23UgsFH;{@ zZtR>2$E11t8P_Ba*W5?TNI=>I@jS%}U2Ls$qLpaq^;juMRIRifQPqOt?E@DR1)8 zStOml)cj~_GZ%!c`uz3O|Jh5!;KL*CPFH25iq*!jQ%zNVK?yzESoBz!CZ`nYz(8GO<~yC5J(1V`Yp@i$l`~K$NM$`-Edt?n(UY zbgo@PM-V-O+t#5p?%H&~-N^;nkcpMJH0x3z36qSpsVWp>xsnuXcP_L)B^yaglGx z`|jr{DYx@r-_yp&B>S_maeD!x{Qjov*XfrpNZ_?B$!WnB+Z6YVl>OFaM9V zZTgGuH}qgNKX27e#`-hjA}|D{hkMF3BAmogn~IG3>)6}ny*sK(sdq9& zZNi)=^fC(}x&eopKNEKADMX#Jj9!<4VH>MqB?mZ=+CTRoL-h&VW)8-~%#r((P;v~T zO-r!Q00!6!k)kJ{poC6ca`Ph;aISY+a|{Hvr5Y1RuQON-E~m#O%4)TLBnA8%p?z7RX(iuY65m_w#X<{^+_U-;ivjiKXCPA~D#<*- zzK|e{78XJ)4uf3UB_J&D{;I}D+Kjv*X~M?n|BI~jbE{Lr$QmAOli3k$4@(~obEV+p z5ckaZE*C^UeCYGYch%Or9_Oi?NLJoDla@{)Va)Hn0suGz!VrM~x zIStDH`K@vmFZ*K`M@CDyCZxPT9?pNAgvlFm{kkvWI*zSP&;t*H5xUfEVtB7N>Vf)x zORLsrkCvw848Fal<?Zk2tDgAaJY4WnlYFmjz-xnJ}|ax(7SDbpGmG5Y# zs^INTH!+7*wY|uzNG%rmh}qAvit9Qn>nHPbL%P4)*5w%Vmq-{eFU@yF4K8t0O&IfP z0Lq4qVMVfN{0Q|f>FEb)WP9}G$7apxKaiBB#NXFtuS*ABKpy z762OJ8INXKmd5~bngVYtWl(&GP55Wq_tR|f9yMhdy~$Pdiwq9V8eexNP0+6%7uaGA z{z!zmkfWqHdR`s428bl0LwNmpU^!@mckv@Nu{a)}ZNc)bmBBmf^WSd6;wuR+=2x{t zFRjtW+NP`Gz1%?ec;c^*hCB=S$txd+m`f8GM$ine?jo4u1J=f?E`yjj)|M8`({+N} z-i7b&u8fiJTi(<`gakcSHdXoX9*T^?R`@p*19;vE3Eg7(<39;+u!=MFoNLC&8hTGC-aZP>LuqMe_^$QqcxYUiij z$5cRKQmzLCaTBlI3lF{I>)`3I6{nycb)kTIG|MrX<08x1CE_~b?e5=`|F?QVr8oPv?P^q^eG>6fq;ZiZNqN2aMF zk7Qxse(j0>4U+xjcqbyoWBrj=Wa0XX5PpxUAcx$2baf1Y$Zqiu7lDc8Iy#xbTP*7- z3bh|1v?-w1fQi2nz~McFmt!*j=5Wk>xvSjHw|%^S#iGVS;mV zd`t|W)q3$6qJ@4TCvhr7k|ZWv?XYHc0r`ey@wF|b|-uqv#2F0G!3NkdO+o-r>8R_r1-D*o;^B$ zcL1p!JX`oXcC)fe!1^$-5!#`ONZfONk6_~l0W|>dOaWXH0io~Zfj5B=RhP?NKVF-N zl0MzXg00^{1-e8iE~o}xD-%14|G8vKkH3E7JnwDqiO8~Br=E6UWXn{D2nHWRrnlN5 zm7i+i)-Pu?t;%Ev7UA-A9D(G&GN^|ac`Bs9X%-2tfAQXTQNo5h_%}n4Gqv1J&u=1W zfS>DKB7kQSb^un&_mB5~pPm3|%S4}BQsnCQ>uPuniB4hgf9qYuaPyjSb*ZNEEqcNi zkz{E1(L#bu1_&Q~AR+{~?^V;*XgiGUyW-eNYup*7vP3i)rRqh4wD4LhTD1{)mJ{gAWO#0g>xq=bB`QH z{@j?t|L`N$=f8Woq?O<_{l22E!uhD;&<8!@nI=MjVSzCS?eKVVt`TGSWOs5}UT zHT3u2Hc~>N#Z^_(o_ZOcR5Hw5#vaE)XD>LRtydqv*Id4(bq!R|afoP}b?^Di*=vYP z8lPQGN6#sz096u`37>e6yBQfS)9Y3-Ln!GE0@-<7 zv||NYEaOK`64P&=>Be&kTAM4s!K!=E4J;k+q>srygBmZ_iDP5^WP9oM-2JvSk0@X( z0qUJw&AMa+E|bd4fwQ?uNgyF+?{Piu20rG{-^yypu$Ye#O_}6&cyBir3|?Qj$B)tF z3*7aT#S$g|Zd#X;GwrVhISyj%+Nb^yd!%H6*|z7*z$VR>Do4}`FJ}g9D#EjlVPRHV zS(r+a^WoszAeg`8`+-+0CcJK}>$>1n2rn%LZTH8n-i}_Lbx;jXj=3tRV&ptkj{){= z^2+V8$Cu`=LYU*B{u4+A#+@z)3Y?v3qmM3nHJ*at*_t1)GenlrdZJB4GnB?W6JrmY zQR|@sN^mF-gb5x!5`_@)JCy(rs&Mpx<~LNC7RLdhK~MZ&(ATFX7+qWW%)^#CbB({K zlc%sc{Sz~?%ID~D`GY|flA!cEd#9I>$i_$0jX_g8fBj51)~DqJ>_)Y9aIH+;g9G{_ zQ0DWXUaT{?4uATMqeE?57CCbbKx2k4=yH`w{)c4uBFmi1KJ6u+Mf>b?41MLdw0pND zUG%I~Zi-*YNq!xVUBh;-#xq+>jrZap#4R0zw+^)jE#+pHo6ez&*dXTuq0Ga`R!9hj zs04y0F1?ah29huqyp7G&CSS=7^O%>5Ff;-{9B44^J>vf79x3aAN4V}>ZX_A!^G&i> ztq5n`zIRRln=hm7v>5)F`hlF+;qhaI2#6*hDE^*a_l?kfo*PrY%0rbW7nzB^oKLOVD-i`YOvGLw$jJ80}(^24~ZfaJF1PKDt$Nb;YVBRRn)MFi8TF!q>B7#Q4 zBu>`mo+29cpcOMuiwcmbcHhu$PAYt~O1YB=Y0r#;^$xmhl0}o&a2X)sA630Us?7VF zt9?-)L-S!F&5(MY*r>h~6GYDgQLZMV4*~aH83=+>rRf68&1 zn9&sz3#3zD`v<7LFj1GEMGy{lw!coD!$@L0(+7c4n1+N_5f@r>5*w;&`48)dPrcqP z(l@C=$waHjBot$C7A1Iyehj@AcqKdsv3MP}s}22n_+-&Uuxj6#5UzNn78!5KoTA^qiRHt-_r7^c;lz_R9v z`B2Wy^y=)!8+1G0o6IqYxZ?4||2D32gGTNYstdyBD=bXQ@ot)+&jW}#NaSd@ZE9&> zYN!NcGGv2zToyI5)YFZFNWaNO;i-D>NlZ8GAn{WRR;}{4Gq&j-iH|Kv;lRD_Vpb${_|e zxw7-hT6ezoGa{1O1)s>|k)W>%{I7zMj6hez769R@Zj&5lbhrqD?MPEtT%IyK1hNqO z6DNp&AKW(>AsPnSjaA-k#J@9BC!oiDALL5&lJ+(H)hJL3N=Igo&A;^;DrnDvxe_cbj};-<>Y4 z1VSc>QL zlWAIT%>Mj-(l;4Z-R8uR4CrweT1e5MyJ~!!2lY)`aR{AVqaFiNtaH^wL#oxM5e1 zo_xIXfBlgttgK=4Brc;X(|X{t`2Ibw_^xL60Blx0`yo5R5(Bf}s!ewSl#y3#~2BL_f|8R?-` z)+-mExC=X4u#1tIuYHJaYv@ftno^P&?qlqQ%luMuXreHvF3SWHPy(Hg`Q3dS40PFu zp>J>wI+*^bdNj!8{@wUPdrdr3W0c_Gm~Bf!xgS`4f1fdbgV znk3;T@Sf{Qag!fOyIsNQMBIckB(oq&}s?q0RF)_mxmE^S3VNW4?2bKry!-%Hp6sGvj zc_b3$1Qh!ZPIKYy8I(+l1f(huV>4C%{VddfKMOECR56(x?G3QA`gvKP`%vRge|$|NixTJ(()Z|A_Q`Nf(&0VCts;pwAYXayd|9wg|Y-YA^OAavBN= zQjMBn>3TB{zX0tb*()ebN;d@f+D@Fcu~ zYSFQIl$fKk1eZa1-sTV!3E5o{;d>oh1?>+PaTRDd626kJyM(`{jcyon&#~a0#KIxW z>oFhwnzYT)_qAnXomujyReAu6(7#-O<|r!Nn(+nvYN#;sH^llN7iWO5W8FOk559!w z=e#_keK%(>BtMC^S+PC$^i6z)C4rT}(`jG_{Ml2sDlKR{TmOPDxVe!s;az0~?J(JGzb$*q9Aldg9-OJHo_< zlAMU(|L0JP=HRBct zpsNrIe0EZcprH&9u^r)=JNHFVE7InhZ8K910cD%AX>4!QvG4^BR2-rSC{|f`BYj_^ zNhFU`pX!4;)&{i43WR0IWpE~ao1%S*xK-2erUWP$sFrhI4AtC{3aGJj6FuzPMSYRyhgfX1>EP zh1JEU^;IU)Vl+Jr0liw~@o{gUywozk_Gr!>{|f6X+}k;$GyMPTbf@sM^hm^onoBF1 zY#ao15khL!Z5EgtVbl=iitZl@CEu_dm9j}^GC>C}512D(X5AbIuI^>^v}7*a#Ylfi z6e>iB_7K#v-Z~v_-g;LUOCia;#7oN4An1&_L6gxfXf? zVZxpaeep5PWK>&Zn;gi-m=zfJgln4}X0#_>p8<==JG9=FKkN`hNYlRCj&M8EFGdS; zDO>U#C&$Skwv^L)#e0UV_loOI-_D{6z_c%x@t18BZRj?ugzIv`=n;jEJZA45y1>bJ zf%5;w*;_|dxpi;DhmurUN*V;DK|rK+(?}VV(jn5_AR;M(n-CDB1q1{Iq@|^#LFq=i zyZPqU^E|&X-tQgbeZTJ?9b=#4-s@iXS~ISB&1=3Mq-)^9QE_wvlXm_@@m8Nz%n4_U zO48zoRx&3Rcg0i^K~FAJ8cm$ll)SVsw21qTNfr-yOmn9C%KNWK*&>di(db({hyNtf z)D%Is5b|+zC`9C&2=ENET2+OOzgMtsQQ0RePzru0U1ODLZ~kl>RlD1hX>mi*FoM-^ zR@{kB^aAB{Lry9l?EuRANP$`#l+!OIU*o?=#7BuP{$Oj0jE~I>uIW#jM|$Pg@7_5q zO$??F3f%m}6N&?&x?vtPJ*H}GO*NH`TYJ;ATY2!Ax)ZehpcZ;YNf0>I>98ve(Y0mP zz#74s)P5J{Sl068S>Cie<^n9COn0La-l!dh>lKn}c zm6ZVV`qAeX8V6jbT~m$Lc(G%ur!WH}Q2}uk&l198fx#%Up7`0M(FTr@FY1(;|0r$& z3GB)B<2OgF6|!Rw*>4qHfDGT5h^X9gFWvkr>tFc^#Ec$qln?I^3qr1tMVCQEwI1fB<=N-my69SQy=rS< zVfqXNu2lHYWbbL!D9eco%*4#(MR_Szi{-ks(omdzjX8hM*KB=R7AHm&ccVIfLe~otbbwCwH`V{K}y(8*=viY^=P}qFMLDswgl?INs0n_7n^DFtKJZ zKi2zwC$iK+(Dh*Fd$In;C)yBx@vo60E7j9xH;L9V7>M=rV-%J+G=3hiqQQbPaih_T-Xd^Ij>UG*1F&u6>sZ)31J%Y2SuDK{htwy>riLO%WO18$~95B%KtfSHWSe zX+7Jx2WamEX zJGlE#+gj@Z^`;_@byeqbAzx=n@0?zsAvcqA5+Ixhnzjm^qE=c?i_P!TYUd~S`*}vX zt!%?eOl4)_h?7jer(#@{yICZW!HQ3Q!_-xH%Pq@lMmq@uOLqdFZwBeQE%{vKNIf)= z_+5uZ+ouUG7>O^sNtzLUX&?iO^<%jdr%RyqcD22Yu>Wq zWRMoCu*4Z9ye`l5;q`mweng!)=HXlng_a6Q*JJT9^ZHj9`nO)Hk#!|1&BsiCC*~bG z+>H%wt2hhP({neH*+PoEtKOV0CDnhq$-&DzcIf=pB_S?YBwLkZU7tuH(>YB3Zg-dT ztC;ZZsWe>`*0gOy^mX4F_eOpqlcuH`V5h^ZN`LIV~YlayK+POpT}+ZH49oY~>a->}TEZnAs{G#t*&= zk9Q{5FVsw(z3M2bupq-9UhXVw1KIY-wf4r9o>s^7e&KoLxjjxSb^Vpf(kLeaN%z@C z@35foBGUr7`9Noz==nXqvd2zV!VB%6ewVZf(c9k7E^j#(om|9o(h|5wBC9(eXyIV< zHLFMY5myIm8?91FAR0yz+mGCbd7DtEPBcUxd}LK>k@}CUJYHQvK*(d{yNZ&`S?X_ujdY^G;!v-Og8vwkK2l`jU)< zDUE&R?CXLpJ>bgUwzf=0Yjjo9G1ZG8{%NHcBZRxB91=<0_DO|$tEbd+j5lW zP39&&LI?xZ!ooZ9+H8JxR46#a9&uItOgQ3t!WMkL=M+Lk6&7YJnUOpENWWR{49=ut z&PrrDXN&2%GG1s&+~5LNhrHr6GFV68;={^-HC`wI9ZpJfsK%?Y%6rq%XT>}_`r9KZ zd+fQ6uY@wxIf(jH@xGIh=sfn2ZCuF6#Q7n7xde<@eS*)8Q`|1Mgi8d+v>+ z>R$|%^?4ZImib(+_YLyJwYUaz(~m*yF9jCTl^>gUNtQ3HGfH|}#IT+?O4Kc^kf9yb zy+`_u&38C(ARJEwZ5G~IhJ}Ua&$-%k#a%q!aS7)6F1=sxofw{EieSwkI`Y$Uu)(M2 zGn5`;l<|JuKyNc^%ceDrCX)2ZDsLaKHiEnJ({sP9*P~{{hbi2|`O}dac}W!b-}Ocs zy<-b-9)^{77^vwJpEado@5|G$tAp1`sA!UROb;1@Q3HH59@Mw6Y~&ns5vp|slM6MQ zTI#Q29v_|(%|&0*+Sb!5=WBd>bn~SL$6=%$yCkb&CQ-@@zCM_tB|hJVlk$A?Bl^j- zEScI@W1O3fl}FT4w+`#SXI~-UUI=Dj4nHIdaXFOvF?ocDuefsCN z#94A7CPE{&k9_{e&y3H0)b(d0g8P6Zt^PQtM!teuenNFsL7C$p^`}!`iybvVyRq3Z z_&Gw!jeWTIN(LVX!FJ92K;tJ+a(yi=x5XWg2fY9mq#2r2_m(p6^hQa}T+=T9nv~8e zI~0QbQPfiZy!2-TJm5R0o>wv6mD9H|nV>`Bx(Idj^fn8pKHttgmEJdu3j}Ie3QKq& zvT|D4un6+z6%DuujduBd$H5dsbK}Kf(Y$n`WWRp8uM+Z_>#`jdS5%ZO3Fq zrkl2ZhdWT0AcKbr*>>SHTB9_8xq9fc&gqBsO~GS#Q6suMHn7buVKhkb3DsIFzC~CV zftZE%0VMmc71~5@JMop{?FfNJZP&nu&v0)mXxTN3c+~2Q4LZKgE3qrrM`del*%A27 z(?nn^s+V)=SCt+-wbo#AO7%K%TMgNcMQ1zuhDTa-q;C|K_ytC9PIW2F zr#^-`NNwLxcE8ZiG{wwVDdDzVn5RkbAOzBo(Ka{VF!v4zfQyaRTduSO z)3+VMkx}BvD8`mk>DkgXP|ryCq)f(<5dRh#4S(^P07Tj>!h?+Rn+;}?x|Wb1=d*E7JJ-BzD87ZKP$YnrhBD#xSe~Lv#MdG%=i4+LJSL!@fWq@djetX;V6*0+;U!?X2 zf*qd97sb*{AKq6JdzLC>5=f+2H8V|NqN|=ty2V++X;j&6-?X?MZHE2`4+-=qkt6DO zy(o01GOHb2sTBkn$HzH{Sx1xRWcj0UA6Gm{3^gAo=Ad$EYrSVH7)dWxLo5P}BWp)) z%v|_(GRxP@=xOo{@wE)Bnn4quR|2W9bu;H|$>b25*4luHHY5JnOBgOp7*zQ2mnXDKW*Gqp83 zE9&~aXUhWHQNfFRj(xOnd1Ibbxqb)P(oW&4c(K5XyZki10Z$TLSnVAr zwuxZ~b_@HTJ@bZj7OV}eqvJMvl5hm{=Dmx?848f*^OI4^ENP*RCa+=rY+-C|YC~C` z6eFJcT(rI-K=!*QJY>gP1OvX0IwV-*rY(N%NP7rT<9pxpFn^BXCPkmr&KjT+^vg983u4xIGB^) z&C67l>BHNvvEVFq6{T)A*Eqtfx%W62tzD6d`pQ8s*BY3fjE@Oc1KRZ5Prb8sYaZ1s zlMdfs;0x}{843Wq?R6;gC`6i%Sr9UJH&yMU#Z;{;Qj{JJs2nYJbO@4 z_?Q{lr^RA37Ku=z5tGjfecp(RxkHhOPzvT%O`zxShfo|?E;8*g91cg@W*$wKz%VCB z0PN(vJb-&~>Lk)|0Q8bt`TX5r1&{4RMHYqle{kuQDL-hT2Hh;Av<7kq3!lhldKb^= zJsruy)%RpI_gFN3W}xzRnpezErns{6i}9#qQv|Kp^(W=y^D<1okDL}9R_3``)Dp(l z&L5MTv@0`xXvz6mcNaabaJ)%ArBI9IL-5$0ZlPFxX`}%htdh^aR+&r7w0?MO(`~mnT)<{KQ6B2IJ|;6B z0F-Riy2V?$zZRxwa^0UeqIT_wcG%IZv2#VFfr(>B@;za! z)uV>t+U}XAFQhqpsx}YuHPFT)oQ%e#%W9O@d=h%(*jKWbXBS zP^0)APrSx?1X6*XpICf#w@6{cv)R0W<*q67@|n-P-9UjB{zj=MMOE2`T(|4DHyl6u zZ}}{Tdwf!!>}u8H<7JxFEq6D%>5;*4embjW+Lnw(x}Z|m&YH*PvCGn!e8+BK;(doz zxHCbw$52z6#z?Krtgv^V6GMT1#fw`GGwHG|SK0M*DcLn^CUdy;TTjrh(A|34G`EgX zNmVe-%;7hF#Cge?9;M^NeARe*{MT#s`8@&iYTj($P|Mj`>7-kPj2`V|hwknMe2zlZ zQhxg1uFM8Uw%q+2Y9oay)T+;Hf}}HRed|xk#6?rVSucXt3U(GY@wrU zY{F1v3UsxbA@_RW^X^>=&Px`57+R4I<E7DOP2oR&rQyDqcI#>X=gaL{+>y+|S4_G}MB{6XC1;vm2MAvt8DrLTT^yzp znk>MTTYkv(2)Ca?RsLPc$8qRbDl@0`^zOlMdfUOz#A-8J`ZO$N$D*@EvRJkV0(=M2yy>c+I8Mcny zvPl1?b~?;SHN%#CI(9|M`Y}P+*J;uF_7VB&)!YV|;z25hWFB~P_4KtD{vw>!fmD;K zEfvKJ>IZuw{7ZS=$U=KbZ?O%%aN2FE^Ri=_ekrWUh;O%3`+mgoKU-EX?TQ-4sr&ll zoBtQV=9#|0S5LQ8l{=26m6_3tJ3o?U_oP__d!6dsP_qnAkQ@m~f$`yW^e2SrGCRlM zC${^WM-=a8t_oRVTvEs^`9*w%W_;X>B>3Kscur(rsQylmd1#EAtdha}lf53STpn~8 z<>#UyZYe{*4~~Xeqw4=8qrL_tMil(*{%ce#(sl<~E|KEfI9(}H8@+FJy3Id~tdpRk znDKM(hrFQAf6Hk;e5vcbLc7@{@7=P4stm*47wp<4|0vb!k03Z|^j4n0C0?p|935Vl zacj^HAtfkxm;}?qAAhk4Bp%adw~uAlYd~mK7LR*v$_F^W#3w#R$CaQ@i{lk)+N$m2 zV!rheougX|^^Mxa&O&(Pyw>S#%(e#+x%v;nnMpY)@{j0~TQ^@?Iv(|zk$&-5tYZ{B z*qHYVPVqe>mcI~x#zf9>qlgl1`{rFmM{UIw4fq9{QjnA11 zpc5q<&Aa=tLoM)Uh5I?vh^y7BMr=YFjpGb8sY;8(km|*yPDnp;NzbgfKD7H8>zNK44>HOB;KZYbdXT2UA4`Y|71_lSNDjtMqiZv zy`FRZ%Fp)My=QKOO`<-_B}YeltA!3TLyF!*g?UF8K1{!V{dVWt8t?y}IA9s(7^^QE z_>6q)Dn~_U_5BUith269V!atp)R;AWB|S;5c0750dv8)Y%R(^0rcaBsga=L&xaB85)mNClbG{;Gby9!y(GWjy$KJA-YtZ&-9lRA@ym`_bKcsUP5#FbD=0 zZ=T^^3gem2dFJyf*PpsvXSNBUl4iT+U>`M8GS9CwAp0g?1{C{=`KFwNl^~Q1kR=X~ z*RX1ixO=qU42G>hqfe0qx-*6;cAzd zYCQ1Cz=N&{+fsqZcma~cU$#vnKc!3tVvr%^V#2!BnpiilbxKEPZ-Gw=9$w zj8RJ~{eEy|CNXvr+*C|!!oJ68wS`UmbE<>`;qz)-c!9zi{$w~O&dUMZG-cGtBK=rT zb3KnwZqMGeHXlD+VU}ONwkVle<+1ju*)GkrB8o7d;%ArWSrtRY@V%o`- z5Z1)EGikxbiR|tBowp75x*lHFGJC*e_TaI@f~q#ne7JYnBa;q&aT+Q?iNK9ootOR+ z*v4(m^eXFWZU`kgiJC`;LIh{tIm7Ed_7^e(JX$pU=OUdU<$JjUBBNFPQn4@;@Kf{V zIWwPIThiyGn6*kjLxh&?Nftw=cY@H5Urph57L*!AX5Ze%SDEreeNZqTIW3yiBA^pt z4PH7U-OYNEE_-N8CTJs2pBVmSXfJsPD@HB5)?ey|;25O{~TO#T^C)pFEW%jZS;A zPwj-nE!6Cz`4UUI^1dPyWhaG>sfmDl&aATHwzF$Jc^H!Pdq)_uN_4k&PA1N>d{(+X zb^J1T`|Gl9fL^qPuhb75M~&De(rlCCCMsYVp*hyXlj@1s3No=0epwp)Bt^oe_%cz% zj?rqL>pIDs;BFNFM6=H%Goz_?6W*!|AO09>n2}*i&*Nf)21h^GEt_=4(uLx-V zG%0i>uj4M=RpM~JbHlRlgG@@APq-mf@?ed@zVU7@9}lN^F(^R+Ar9REYV-CxkqA!x12P2bPpsnGnI@Yaesud;}V>?Q`(M|qtQ8&qYotlx640Kzr5}b!aSrv z5Nw1IV*w=35$&nYE8n7{6gZFqm~Shxo)W`SNjSK5JzK4^ (u28NaP_`zveNrEkPsUd#?~s+Oe^ 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 diff --git a/exaudfclient/exa_udf_client.cc b/exaudfclient/exa_udf_client.cc new file mode 100644 index 0000000..8359c04 --- /dev/null +++ b/exaudfclient/exa_udf_client.cc @@ -0,0 +1,25 @@ +#include +#include + +#include "exa_udf_client.h" +#include "exa_vm_factory.h" + +void ExaUdfClient::parse_arguments(int argc, char** argv) { + m_languageArg = argv[2]; +} + +bool ExaUdfClient::validate_arguments(int argc, char** argv) { + if (argc != 3 || strcmp(argv[2], "lang=python") != 0) { + usage(argv[0]); + return false; + } + return true; +} + +void ExaUdfClient::usage(const std::string& programName) { + std::cerr << "Usage: " << programName << " lang=python" << std::endl; +} + +std::function ExaUdfClient::create_vm() { + return ::create_vm(m_languageArg); +} diff --git a/exaudfclient/exa_udfclient_binary_common/exa_udf_client.h b/exaudfclient/exa_udf_client.h similarity index 88% rename from exaudfclient/exa_udfclient_binary_common/exa_udf_client.h rename to exaudfclient/exa_udf_client.h index 062c3f5..8fc8881 100644 --- a/exaudfclient/exa_udfclient_binary_common/exa_udf_client.h +++ b/exaudfclient/exa_udf_client.h @@ -1,7 +1,8 @@ #pragma once + #include -#include "exa_udf_base.h" +#include "exa_udfclient_binary_common/exa_udf_base.h" #include "exaudflib/vm/swig_vm.h" class ExaUdfClient : public ExaUdfClientBase { @@ -11,7 +12,7 @@ class ExaUdfClient : public ExaUdfClientBase { void usage(const std::string& programName) override; bool validate_arguments(int argc, char** argv) override; std::function create_vm() override; - + protected: std::string m_languageArg; }; diff --git a/exaudfclient/exa_udfclient.cc b/exaudfclient/exa_udfclient.cc index 37aae3a..4a1935c 100644 --- a/exaudfclient/exa_udfclient.cc +++ b/exaudfclient/exa_udfclient.cc @@ -1,6 +1,6 @@ -#include "exa_udfclient_binary_common/exa_udf_client.h" +#include "exa_udf_client.h" int main(int argc, char **argv) { ExaUdfClient client; return client.startClientBase(argc, argv); -} \ No newline at end of file +} diff --git a/exaudfclient/exa_udfclient_binary_common/exa_lib_loader.cc b/exaudfclient/exa_udfclient_binary_common/exa_lib_loader.cc deleted file mode 100644 index de05b03..0000000 --- a/exaudfclient/exa_udfclient_binary_common/exa_lib_loader.cc +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include - -#include "exa_lib_loader.h" -#include "utils/debug_message.h" - -namespace exa_lib { - void* load_library(const std::string& stdLibPath) { - if(stdLibPath.empty()) { - return nullptr; - } - - void* handle = dlmopen(LM_ID_NEWLM, stdLibPath.c_str(), RTLD_NOW); - if(!handle) { - std::cerr << "dlmopen error: " << dlerror() << "; while loading " << stdLibPath << std::endl; - return nullptr; - } - return handle; - } - - void* load_symbol(void *handle, const std::string& symbol_name) { - void *p_res = nullptr; - char *error = nullptr; - if(handle) { - p_res = dlsym(handle, symbol_name.c_str()); - - if((error = dlerror()) != nullptr) { - std::cerr << "Error when trying to load symbol '" << symbol_name << "': " << error << std::endl; - return nullptr; - } - } - return p_res; - } -} diff --git a/exaudfclient/exa_udfclient_binary_common/exa_lib_loader.h b/exaudfclient/exa_udfclient_binary_common/exa_lib_loader.h deleted file mode 100644 index 4bc0c88..0000000 --- a/exaudfclient/exa_udfclient_binary_common/exa_lib_loader.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include - -namespace exa_lib { - void* load_library(const std::string& stdLibPath); - void* load_symbol(void *handle, const std::string& symbol_name); -} \ No newline at end of file diff --git a/exaudfclient/exa_udfclient_binary_common/exa_set_env.cc b/exaudfclient/exa_udfclient_binary_common/exa_set_env.cc deleted file mode 100644 index 5718d1b..0000000 --- a/exaudfclient/exa_udfclient_binary_common/exa_set_env.cc +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "exaudflib/vm/swig_vm.h" -#include "exa_set_env.h" - -namespace exa_env { - void setup_environment() { - if (::setenv("HOME", "/tmp", 1) == -1) { - std::cerr << "Failed setting HOME env var: " << std::strerror(errno) << std::endl; - throw SWIGVMContainers::SWIGVM::exception("Failed to set HOME directory"); - } - if (::setlocale(LC_ALL, "en_US.utf8") == nullptr) { - std::cerr << "Failed setting locale: " << std::strerror(errno) << std::endl; - throw SWIGVMContainers::SWIGVM::exception("Failed to set locale"); - } - } -} \ No newline at end of file diff --git a/exaudfclient/exa_udfclient_binary_common/exa_set_env.h b/exaudfclient/exa_udfclient_binary_common/exa_set_env.h deleted file mode 100644 index 9f6c822..0000000 --- a/exaudfclient/exa_udfclient_binary_common/exa_set_env.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -namespace exa_env { - void setup_environment(); -} diff --git a/exaudfclient/exa_udfclient_binary_common/exa_udf_base.cc b/exaudfclient/exa_udfclient_binary_common/exa_udf_base.cc deleted file mode 100644 index 56710fb..0000000 --- a/exaudfclient/exa_udfclient_binary_common/exa_udf_base.cc +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include -#include - -#include "exaudf_lib_output_path.h" -#include "exaudflib/vm/swig_vm.h" -#include "exa_udf_base.h" -#include "exa_lib_loader.h" -#include "exa_set_env.h" -#include "exaudflib/load_dynamic.h" -#include "utils/debug_message.h" - -namespace SWIGVMContainers { -__thread SWIGVM_params_t * SWIGVM_params = nullptr; -} - -int ExaUdfClientBase::startClientBase(int argc, char** argv) { - if (!validate_arguments(argc, argv)) { - usage(argv[0]); - exit(EXIT_FAILURE); - } - parse_arguments(argc, argv); - - std::string libexaudflibPath; -#ifdef CUSTOM_LIBEXAUDFLIB_PATH - libexaudflibPath = std::string(CUSTOM_LIBEXAUDFLIB_PATH); -#else - libexaudflibPath = std::string(::getenv("LIBEXAUDFLIB_PATH")); -#endif - DBGMSG(std::cerr, "Load libexaudflib"); - DBGVAR(std::cerr, libexaudflibPath); - void* exaudflib_handle = exa_lib::load_library(libexaudflibPath); - if (!exaudflib_handle) { - std::cerr << "Failed to load library: " << libexaudflibPath << std::endl; - exit(EXIT_FAILURE); - } - set_exaudflib_handle(exaudflib_handle); - - MAIN_FUN exaudfclient_main = (MAIN_FUN)exa_lib::load_symbol(exaudflib_handle, "exaudfclient_main"); - SET_SWIGVM_PARAMS set_SWIGVM_params = (SET_SWIGVM_PARAMS)exa_lib::load_symbol(exaudflib_handle, "set_SWIGVM_params"); - - exa_env::setup_environment(); - std::function vmMaker = create_vm(); - - SWIGVMContainers::SWIGVM_params = new SWIGVMContainers::SWIGVM_params_t(true); - set_SWIGVM_params(SWIGVMContainers::SWIGVM_params); - return exaudfclient_main(vmMaker, argc, argv); -} \ No newline at end of file diff --git a/exaudfclient/exa_udfclient_binary_common/exa_udf_base.h b/exaudfclient/exa_udfclient_binary_common/exa_udf_base.h deleted file mode 100644 index 59eb30b..0000000 --- a/exaudfclient/exa_udfclient_binary_common/exa_udf_base.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -#include -#include - -#include "exaudflib/vm/swig_vm.h" - -typedef bool (*SET_SWIGVM_PARAMS)(SWIGVMContainers::SWIGVM_params_t*); -typedef int (*MAIN_FUN)(std::function vmMaker, int, char**); - -class ExaUdfClientBase { -public: - virtual ~ExaUdfClientBase() = default; - virtual void usage(const std::string& programName) = 0; - virtual std::function create_vm() = 0; - virtual bool validate_arguments(int argc, char** argv) = 0; - virtual void parse_arguments(int argc, char** argv) = 0; - virtual int startClientBase(int argc, char** argv); -}; \ No newline at end of file diff --git a/exaudfclient/exa_udfclient_binary_common/exa_udf_client.cc b/exaudfclient/exa_udfclient_binary_common/exa_udf_client.cc deleted file mode 100644 index 3b5ea09..0000000 --- a/exaudfclient/exa_udfclient_binary_common/exa_udf_client.cc +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include - -#include "exa_udf_client.h" -#include "exa_vm_factory.h" - -void ExaUdfClient::parse_arguments(int argc, char** argv) { - // Now assumption is that all cmd line aguments are already validated. - m_languageArg = argv[2]; - -} - -bool ExaUdfClient::validate_arguments(int argc, char** argv) { - if (argc != 3) { - usage(argv[0]); - return false; - } - - if (!((strcmp(argv[2], "lang=python") == 0) - || (strcmp(argv[2], "lang=streaming") == 0) - || (strcmp(argv[2], "lang=benchmark") == 0))) { - usage(argv[0]); - return false; - } - - return true; -} - -void ExaUdfClient::usage(const std::string& programName) { - std::cerr << "Usage: " << programName - << " lang=python|lang=streaming|lang=benchmark" - << std::endl; -} - -std::function ExaUdfClient::create_vm() { - return ::create_vm(m_languageArg, false); -} diff --git a/exaudfclient/exa_udfclient_binary_common/exa_vm_factory.cc b/exaudfclient/exa_udfclient_binary_common/exa_vm_factory.cc deleted file mode 100644 index b6a3770..0000000 --- a/exaudfclient/exa_udfclient_binary_common/exa_vm_factory.cc +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include "exa_vm_factory.h" - -#ifdef ENABLE_PYTHON_VM -#include "python/pythoncontainer.h" -#endif //ENABLE_PYTHON_VM - -#ifdef ENABLE_STREAMING_VM -#include "streaming_container/streamingcontainer.h" -#endif - -#ifdef ENABLE_BENCHMARK_VM -#include "benchmark_container/benchmark_container.h" -#endif - -std::function create_vm(const std::string& argv_lang, bool use_ctpg_options_parser) { - if(argv_lang.compare("lang=python") == 0) { - #ifdef ENABLE_PYTHON_VM - char *path_var = getenv("PATH"); - if(path_var != NULL) { - std::string path_var_str = std::string(path_var); - path_var_str.insert(0, "/opt/conda/bin:"); - if (::setenv("PATH", path_var_str.c_str(), 1) == -1) { - std::cerr << "Unable to prefix PATH env variable with /opt/conda/bin"; - } - } - return []() { return new SWIGVMContainers::PythonVM(false); }; - #else - throw SWIGVMContainers::SWIGVM::exception("this exaudfclient has been compilied without Python support"); - #endif - } - else if(argv_lang.compare("lang=streaming") == 0) { - #ifdef ENABLE_STREAMING_VM - return []() { return new SWIGVMContainers::StreamingVM(false); }; - #else - throw SWIGVMContainers::SWIGVM::exception("this exaudfclient has been compilied without Streaming support"); - #endif - } - else if(argv_lang.compare("lang=benchmark") == 0) { - #ifdef ENABLE_BENCHMARK_VM - return []() { return new SWIGVMContainers::BenchmarkVM(false); }; - #else - throw SWIGVMContainers::SWIGVM::exception("this exaudfclient has been compilied without Benchmark support"); - #endif - } - else { - throw SWIGVMContainers::SWIGVM::exception("unsupported language specified in argv"); - } -} diff --git a/exaudfclient/exa_vm_factory.cc b/exaudfclient/exa_vm_factory.cc new file mode 100644 index 0000000..e778863 --- /dev/null +++ b/exaudfclient/exa_vm_factory.cc @@ -0,0 +1,18 @@ +#include + +#include "exa_vm_factory.h" + +#ifdef ENABLE_PYTHON_VM +#include "base/python/pythoncontainer.h" +#endif + +std::function create_vm(const std::string& argv_lang) { + if (argv_lang != "lang=python") { + throw SWIGVMContainers::SWIGVM::exception("unsupported language specified in argv"); + } +#ifdef ENABLE_PYTHON_VM + return []() { return new SWIGVMContainers::PythonVM(false); }; +#else + throw SWIGVMContainers::SWIGVM::exception("this exaudfclient has been compiled without Python support"); +#endif +} diff --git a/exaudfclient/exa_udfclient_binary_common/exa_vm_factory.h b/exaudfclient/exa_vm_factory.h similarity index 64% rename from exaudfclient/exa_udfclient_binary_common/exa_vm_factory.h rename to exaudfclient/exa_vm_factory.h index 7d9e306..617bd81 100644 --- a/exaudfclient/exa_udfclient_binary_common/exa_vm_factory.h +++ b/exaudfclient/exa_vm_factory.h @@ -1,4 +1,8 @@ #pragma once + +#include +#include + #include "exaudflib/vm/swig_vm.h" -std::function create_vm(const std::string& argv_lang, bool use_ctpg_options_parser); +std::function create_vm(const std::string& argv_lang); diff --git a/exaudfclient/base/exaudfclient.template.sh b/exaudfclient/exaudfclient.template.sh similarity index 72% rename from exaudfclient/base/exaudfclient.template.sh rename to exaudfclient/exaudfclient.template.sh index 68d5af9..fffd9a3 100644 --- a/exaudfclient/base/exaudfclient.template.sh +++ b/exaudfclient/exaudfclient.template.sh @@ -3,12 +3,12 @@ SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" echo "Changing to script directory $SCRIPT_DIR" cd "$SCRIPT_DIR" || return 1 -export LIBPYEXADATAFRAME_DIR="$SCRIPT_DIR/external/exaudfclient_base+/python/python3" +export LIBPYEXADATAFRAME_DIR="$SCRIPT_DIR/base/python/python3" if [[ -d /opt/conda ]] then export CONDA_DEFAULT_ENV=base export CONDA_PREFIX=/opt/conda export MAMBA_ROOT_PREFIX=$CONDA_PREFIX - export LD_LIBRARY_PATH="$CONDA_PREFIX/cuda-compat/:$LD_LIBRARY_PATH" # Temporary hack for the Cuda ML flavor(s) + export LD_LIBRARY_PATH="$CONDA_PREFIX/cuda-compat/:$LD_LIBRARY_PATH" fi diff --git a/exaudfclient/run_local.sh b/exaudfclient/run_local.sh index 68368ec..f7a5565 100644 --- a/exaudfclient/run_local.sh +++ b/exaudfclient/run_local.sh @@ -4,4 +4,4 @@ #shellcheck disable=SC1091 source .env export VERBOSE_BUILD="--subcommands --verbose_failures" -bash run.sh --define streaming=true --define python=true --define benchmark=true "$@" +bash run.sh --define python=true "$@" diff --git a/exaudfclient/variables.bzl b/exaudfclient/variables.bzl index 0d5fc1b..62e8c42 100644 --- a/exaudfclient/variables.bzl +++ b/exaudfclient/variables.bzl @@ -1,13 +1,5 @@ -BENCHMARK_VM_ENABLED_DEFINE=select({ - "@exaudfclient_base//:benchmark": ["ENABLE_BENCHMARK_VM"], - "//conditions:default": [] - }) -STREAMING_VM_ENABLED_DEFINE=select({ - "@exaudfclient_base//:bash": ["ENABLE_STREAMING_VM"], - "//conditions:default": [] - }) PYTHON_VM_ENABLED_DEFINE=select({ - "@exaudfclient_base//:python": ["ENABLE_PYTHON_VM"], + "//:python": ["ENABLE_PYTHON_VM"], "//conditions:default": [] }) -VM_ENABLED_DEFINES=BENCHMARK_VM_ENABLED_DEFINE+PYTHON_VM_ENABLED_DEFINE+STREAMING_VM_ENABLED_DEFINE +VM_ENABLED_DEFINES=PYTHON_VM_ENABLED_DEFINE diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile index 555207c..a034ddc 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -20,5 +20,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/exaudflib/zmqcontainer.proto /exasol_emulator +COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile index 26623b7..c3ea61a 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -22,5 +22,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/exaudflib/zmqcontainer.proto /exasol_emulator +COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile index 0680c99..7d26473 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile @@ -21,5 +21,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/exaudflib/zmqcontainer.proto /exasol_emulator +COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile index 5637382..95f2027 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile @@ -38,5 +38,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/exaudflib/zmqcontainer.proto /exasol_emulator +COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile index 555207c..a034ddc 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile @@ -20,5 +20,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/exaudflib/zmqcontainer.proto /exasol_emulator +COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile index 5637382..95f2027 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile @@ -38,5 +38,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/exaudflib/zmqcontainer.proto /exasol_emulator +COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile index 555207c..a034ddc 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile @@ -20,5 +20,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/exaudflib/zmqcontainer.proto /exasol_emulator +COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. From 6096a61798f5e1d8880b42cfd885483014a05914 Mon Sep 17 00:00:00 2001 From: Torsten Kilias Date: Mon, 31 Aug 2026 12:12:15 +0200 Subject: [PATCH 02/32] Build: fetch emulator schema from udf-runner-cpp --- exaudfclient/base/zmqcontainer.proto | 260 ------------------ .../base_test_build_run/Dockerfile | 4 +- .../base_test_build_run/Dockerfile | 4 +- .../base_test_build_run/Dockerfile | 4 +- .../base_test_build_run/Dockerfile | 4 +- .../base_test_build_run/Dockerfile | 4 +- .../base_test_build_run/Dockerfile | 4 +- .../base_test_build_run/Dockerfile | 4 +- 8 files changed, 21 insertions(+), 267 deletions(-) delete mode 100644 exaudfclient/base/zmqcontainer.proto diff --git a/exaudfclient/base/zmqcontainer.proto b/exaudfclient/base/zmqcontainer.proto deleted file mode 100644 index 00ef7a5..0000000 --- a/exaudfclient/base/zmqcontainer.proto +++ /dev/null @@ -1,260 +0,0 @@ -syntax = "proto2"; - -option optimize_for = LITE_RUNTIME; -// --- data definition --------------------------------------------------------- - -enum column_type { - PB_UNSUPPORTED = 0; // represents following SQL types: - PB_DOUBLE = 1; // FLOAT - PB_INT32 = 2; // DECIMAL(4, 0) - PB_INT64 = 3; // DECIMAL(8, 0) - PB_NUMERIC = 4; // all other numeric types - PB_TIMESTAMP = 5; // TIMESTAMP - PB_DATE = 6; // DATE - PB_STRING = 7; // CHAR or VARCHAR - PB_BOOLEAN = 8; // BOOL -} - -// type of iteration: -// scalar, returns -> PB_EXACTLY_ONCE -// set, emits -> PB_MULTIPLE -enum iter_type { PB_EXACTLY_ONCE = 1; PB_MULTIPLE = 2; }; - -message exascript_metadata { - message column_definition { - // Name of column as UTF-8 String - required string name = 1; - // Type of column (see "enum column_type") - optional column_type type = 2; - // Type name how it is shown in EXASolution - required string type_name = 3; - // Size of Type, for CHAR and VARCHAR types - optional uint32 size = 4; - // Precision, for DECIMAL types - optional uint32 precision = 5; - // Scale, for DECIMAL types - optional uint32 scale = 6; - } - required iter_type input_iter_type = 1; - required iter_type output_iter_type = 2; - - repeated column_definition input_columns = 3; - repeated column_definition output_columns = 4; - - // If set, do not enter the run() state but instead wait for single - // synchronous function invokations - required bool single_call_mode = 5; -} - -message exascript_table_data { - // Rows count in current message - required uint64 rows = 1; - // Rows count in current group in EXASolution - // Can be 0 if no group defined - required uint64 rows_in_group = 8; - - // Storage for following types: NUMERIC, TIMESTAMP, DATE and STRING - repeated string data_string = 2; - - repeated bool data_nulls = 3 [packed = true]; - repeated bool data_bool = 4 [packed = true]; - repeated int32 data_int32 = 5 [packed = true]; - repeated int64 data_int64 = 6 [packed = true]; - repeated double data_double = 7 [packed = true]; - // Local row numbers - repeated uint64 row_number = 9 [packed = true]; -} - -// --- initialization process -------------------------------------------------- - -message exascript_client { - // URL of the client in form: tcp://10.10.1.1:2000 - required string client_name = 1; - // UTF-8 Text, which is received from redirector and send to VM - // This string will not be interpreted by EXASolution - optional string meta_info = 2; -} - -/* -enum exascript_vmtype { - PB_VM_UNSUPPORTED = 0; - PB_VM_PYTHON = 1; - PB_VM_SCHEME = 2; - PB_VM_JAVASCRIPT = 3; - PB_VM_R = 4; - PB_VM_EXTERNAL = 5; - PB_VM_JAVA = 6; - PM_VM_PLUGIN_LANGUAGE = 7; -} -*/ - -message exascript_info { - required string database_name = 1; - required string database_version = 2; - required string script_name = 3; - required string source_code = 4; - // Session ID: long unique number of current session in EXASolution - required uint64 session_id = 5; - // Number of SQL Statement in current Session - required uint32 statement_id = 6; - // Number of nodes in EXASolution - required uint32 node_count = 7; - // Current node number, starting at 0 - required uint32 node_id = 8; - // Long unique number of VM - required uint64 vm_id = 9; - // Type of the VM - //required exascript_vmtype vm_type = 10; - // A VM should not exceed this memory limit - // For external UDF's it doesn't matter - required uint64 maximal_memory_limit = 11; - // meta_info contains the string from meta_info in exascript_client message - optional string meta_info = 12; - required string script_schema = 13; - optional string current_user = 14; - optional string current_schema = 15; - optional string scope_user = 16; -} -message exascript_ping { - // the string from exascript_client message - required string meta_info = 1; -} - -// --- connection finalization ------------------------------------------------- - -message exascript_close { - optional string exception_message = 1; -} - -// --- script and other imports -------------------------------------------------------- - -enum import_type { - PB_IMPORT_SCRIPT_CODE = 1; - PB_IMPORT_CONNECTION_INFORMATION = 2; -} - -message exascript_import_req { - required string script_name = 1; // todo?: rename to "object_name" - optional import_type kind = 2 [default=PB_IMPORT_SCRIPT_CODE]; -} - -message connection_information_rep { - required string kind = 1; - required string address = 2; - required string user = 3; - required string password = 4; -} - -message exascript_import_rep { - optional string source_code = 1; - optional string exception_message = 2; - optional connection_information_rep connection_information = 3; -} - -// --- sending data from exasolution to process -------------------------------- - -message exascript_next_data_rep { - required exascript_table_data table = 2; -} - -// --- sending data from process to exasolution -------------------------------- - -message exascript_emit_data_req { - required exascript_table_data table = 2; -} - -// --- sending a single result from process to exasolution --------------------- -message exascript_return_req { - required string result = 1; -} - -message exascript_undefined_call_req { - required string remote_fn = 1; -} - -enum single_call_function_id { - SC_FN_NIL = 0; - SC_FN_DEFAULT_OUTPUT_COLUMNS = 1; - SC_FN_VIRTUAL_SCHEMA_ADAPTER_CALL = 2; - SC_FN_GENERATE_SQL_FOR_IMPORT_SPEC = 3; - SC_FN_GENERATE_SQL_FOR_EXPORT_SPEC = 4; -} - - -message key_value_pair { - required string key = 1; - required string value = 2; -} - -message import_specification_rep { - required bool is_subselect = 1; - optional connection_information_rep connection_information = 2; - optional string connection_name = 3; - repeated exascript_metadata.column_definition subselect_column_specification = 4; - repeated key_value_pair parameters = 5; -} - -message export_specification_rep { - required bool has_truncate = 1; - required bool has_replace = 2; - optional string created_by = 3; - repeated string source_column_names = 4; - optional connection_information_rep connection_information = 5; - optional string connection_name = 6; - repeated key_value_pair parameters = 7; -} - -message exascript_single_call_rep { - required single_call_function_id fn = 1; - optional import_specification_rep import_specification = 2; - optional string json_arg = 3; - optional export_specification_rep export_specification = 4; -} - -// --- general request and response messages ----------------------------------- - -enum message_type { - MT_UNKNOWN = 0; - MT_CLIENT = 1; - MT_INFO = 2; - MT_META = 3; - MT_CLOSE = 4; - MT_IMPORT = 5; - MT_NEXT = 6; - MT_RESET = 7; - MT_EMIT = 8; - MT_RUN = 9; - MT_DONE = 10; - MT_CLEANUP = 11; - MT_FINISHED = 12; - MT_PING_PONG = 13; - MT_TRY_AGAIN = 14; - MT_CALL = 15; // this message request the synchronous invocation of a function in the remote container - MT_RETURN = 16; // this message is used to communicate the result of a synchronous function invocation from the container to EXASolution - MT_UNDEFINED_CALL = 17; // this message tells EXASolution that the requested function in not available in the container -} - -; - -message exascript_request { - required message_type type = 1; - required uint64 connection_id = 2; - optional exascript_client client = 3; /* E-UDF service -> EXASolution */ - optional exascript_info info = 4; /* EXASolution -> Redirector */ - optional exascript_close close = 5; - optional exascript_import_req import = 6; - optional exascript_emit_data_req emit = 7; - optional exascript_ping ping = 8; - optional exascript_return_req call_result = 9; - optional exascript_undefined_call_req undefined_call = 10; -} - -message exascript_response { - required message_type type = 1; - required uint64 connection_id = 2; - optional exascript_client client = 3; /* Redirector -> EXASolution */ - optional exascript_info info = 4; /* EXASolution -> E-UDF service */ - optional exascript_metadata meta = 5; - optional exascript_close close = 6; - optional exascript_import_rep import = 7; - optional exascript_next_data_rep next = 8; diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile index a034ddc..a812477 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -1,5 +1,7 @@ FROM {{base_test_deps}} +ARG UDF_RUNNER_CPP_COMMIT=b3a8c204a2555b373c66110d5e8301a374b32a6a + RUN mkdir /conf /buckets RUN exaslpm export-variables --out-file /env @@ -20,5 +22,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile index c3ea61a..fcfb71f 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -1,5 +1,7 @@ FROM {{base_test_deps}} +ARG UDF_RUNNER_CPP_COMMIT=b3a8c204a2555b373c66110d5e8301a374b32a6a + RUN mkdir /conf /buckets RUN exaslpm export-variables --out-file /env @@ -22,5 +24,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile index 7d26473..8c2cc00 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile @@ -1,5 +1,7 @@ FROM {{base_test_deps}} +ARG UDF_RUNNER_CPP_COMMIT=b3a8c204a2555b373c66110d5e8301a374b32a6a + RUN mkdir /conf /buckets RUN exaslpm export-variables --out-file /env @@ -21,5 +23,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile index 95f2027..d155d3e 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile @@ -1,5 +1,7 @@ FROM {{language_deps}} +ARG UDF_RUNNER_CPP_COMMIT=b3a8c204a2555b373c66110d5e8301a374b32a6a + RUN mkdir /conf /buckets COPY --from={{base_test_deps}} /usr /usr @@ -38,5 +40,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile index a034ddc..a812477 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile @@ -1,5 +1,7 @@ FROM {{base_test_deps}} +ARG UDF_RUNNER_CPP_COMMIT=b3a8c204a2555b373c66110d5e8301a374b32a6a + RUN mkdir /conf /buckets RUN exaslpm export-variables --out-file /env @@ -20,5 +22,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile index 95f2027..d155d3e 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile @@ -1,5 +1,7 @@ FROM {{language_deps}} +ARG UDF_RUNNER_CPP_COMMIT=b3a8c204a2555b373c66110d5e8301a374b32a6a + RUN mkdir /conf /buckets COPY --from={{base_test_deps}} /usr /usr @@ -38,5 +40,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile index a034ddc..a812477 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile @@ -1,5 +1,7 @@ FROM {{base_test_deps}} +ARG UDF_RUNNER_CPP_COMMIT=b3a8c204a2555b373c66110d5e8301a374b32a6a + RUN mkdir /conf /buckets RUN exaslpm export-variables --out-file /env @@ -20,5 +22,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -COPY /exaudfclient/base/zmqcontainer.proto /exasol_emulator +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. From af8e6c1086ebdba319ea2e37c7868a725988a15e Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Mon, 31 Aug 2026 16:40:51 +0530 Subject: [PATCH 03/32] fix bazel tests --- .github/workflows/check_bazel_tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check_bazel_tests.yml b/.github/workflows/check_bazel_tests.yml index 14e0131..78d0594 100644 --- a/.github/workflows/check_bazel_tests.yml +++ b/.github/workflows/check_bazel_tests.yml @@ -32,7 +32,7 @@ jobs: fail-fast: false matrix: include: - - test: "//exaudflib/test/..." + - test: "@exaudfclient_base//exaudflib/test/..." name: "exaudflib" steps: - uses: actions/checkout@v6 @@ -52,7 +52,7 @@ jobs: - name: Run tests run: | bazel test ${{ matrix.additional_args }} ${{ matrix.test }} - working-directory: ./exaudfclient/base + working-directory: ./exaudfclient env: OPENSSL_LIBRARY_PREFIX: "/usr/lib/x86_64-linux-gnu" OPENSSL_INCLUDE_PREFIX: "/usr/include/openssl" From 3f9ecf92ea40e4c2f88156210d4f0f8d3dd98b47 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Mon, 31 Aug 2026 16:56:58 +0530 Subject: [PATCH 04/32] Fix protobuf fixture used by base test images --- .../flavor_base/base_test_build_run/Dockerfile | 3 ++- .../flavor_base/base_test_build_run/Dockerfile | 3 ++- .../flavor_base/base_test_build_run/Dockerfile | 3 ++- .../flavor_base/base_test_build_run/Dockerfile | 3 ++- .../flavor_base/base_test_build_run/Dockerfile | 3 ++- .../flavor_base/base_test_build_run/Dockerfile | 3 ++- .../flavor_base/base_test_build_run/Dockerfile | 3 ++- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile index a812477..7e4b36d 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -22,5 +22,6 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ + && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile index fcfb71f..d37d648 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -24,5 +24,6 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ + && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile index 8c2cc00..a336d3e 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile @@ -23,5 +23,6 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ + && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile index d155d3e..f2b5891 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile @@ -40,5 +40,6 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ + && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile index a812477..7e4b36d 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile @@ -22,5 +22,6 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ + && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile index d155d3e..f2b5891 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile @@ -40,5 +40,6 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ + && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile index a812477..7e4b36d 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile @@ -22,5 +22,6 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ + && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. From 488648eac47e9dc4959762276c66ae692beca20c Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Mon, 31 Aug 2026 16:57:19 +0530 Subject: [PATCH 05/32] Preserve Conda bin directory in runner PATH --- exaudfclient/exa_vm_factory.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/exaudfclient/exa_vm_factory.cc b/exaudfclient/exa_vm_factory.cc index e778863..1133971 100644 --- a/exaudfclient/exa_vm_factory.cc +++ b/exaudfclient/exa_vm_factory.cc @@ -1,4 +1,6 @@ #include +#include +#include #include "exa_vm_factory.h" @@ -11,6 +13,14 @@ std::function create_vm(const std::string& argv_lan throw SWIGVMContainers::SWIGVM::exception("unsupported language specified in argv"); } #ifdef ENABLE_PYTHON_VM + char *path_var = getenv("PATH"); + if (path_var != nullptr) { + std::string path_var_str = std::string(path_var); + path_var_str.insert(0, "/opt/conda/bin:"); + if (setenv("PATH", path_var_str.c_str(), 1) == -1) { + std::cerr << "Unable to prefix PATH env variable with /opt/conda/bin"; + } + } return []() { return new SWIGVMContainers::PythonVM(false); }; #else throw SWIGVMContainers::SWIGVM::exception("this exaudfclient has been compiled without Python support"); From 187e0a0d29e0d99628cd8bdf928024bd5af53756 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Mon, 31 Aug 2026 19:32:04 +0530 Subject: [PATCH 06/32] Set dependency paths for Bazel flavor builds --- .../flavor_base/base_test_build_run/Dockerfile | 7 ++++++- .../flavor_base/build_run/Dockerfile | 7 ++++++- .../flavor_base/base_test_build_run/Dockerfile | 7 ++++++- .../flavor_base/build_run/Dockerfile | 7 ++++++- .../flavor_base/base_test_build_run/Dockerfile | 7 ++++++- .../flavor_base/build_run/Dockerfile | 7 ++++++- .../flavor_base/base_test_build_run/Dockerfile | 2 +- .../flavor_base/build_run/Dockerfile | 2 +- .../flavor_base/base_test_build_run/Dockerfile | 7 ++++++- .../flavor_base/base_test_build_run/Dockerfile | 2 +- .../flavor_base/build_run/Dockerfile | 2 +- .../flavor_base/base_test_build_run/Dockerfile | 7 ++++++- 12 files changed, 52 insertions(+), 12 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile index 7e4b36d..a4929b7 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -12,7 +12,12 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && \ + export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ + ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ + ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/build_run/Dockerfile index 6ae21ce..2309c69 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/build_run/Dockerfile @@ -7,7 +7,12 @@ RUN exaslpm export-variables --out-file /env WORKDIR /exaudfclient/ -RUN source /env && ./build.sh --config no-tty --config optimize --config python --config slow-wrapper --config fix_conda_ar_tool +RUN source /env && \ + export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ + ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ + ./build.sh --config no-tty --config optimize --config python --config slow-wrapper --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile index d37d648..556db6f 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -13,7 +13,12 @@ COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && \ + export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ + ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ + ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/build_run/Dockerfile index ce52b90..928e8a6 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/build_run/Dockerfile @@ -7,7 +7,12 @@ RUN exaslpm export-variables --out-file /env WORKDIR /exaudfclient/ -RUN source /env && ./build.sh --config no-tty --config optimize --config python --config slow-wrapper --config fix_conda_ar_tool +RUN source /env && \ + export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ + ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ + ./build.sh --config no-tty --config optimize --config python --config slow-wrapper --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile index a336d3e..8d208f5 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile @@ -13,7 +13,12 @@ COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ # We need to build with optimize here, because the debug build fails to run with a runtime linking error regarding protobuf -RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && \ + export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ + ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ + ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/build_run/Dockerfile index 2e31703..37cfd87 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/build_run/Dockerfile @@ -7,7 +7,12 @@ COPY exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && ./build.sh --config no-tty --config optimize --config python --config fast-binary --config fix_conda_ar_tool +RUN source /env && \ + export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ + ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ + ./build.sh --config no-tty --config optimize --config python --config fast-binary --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile index f2b5891..89bf464 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile @@ -30,7 +30,7 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN ["/bin/bash", "-c", "source /env && bash build.sh --config no-tty -c dbg --config python --config test-binaries"] +RUN ["/bin/bash", "-c", "source /env && export PROTOBUF_LIBRARY_PREFIX=\"${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" PROTOBUF_INCLUDE_PREFIX=\"${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" ZMQ_LIBRARY_PREFIX=\"${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" ZMQ_INCLUDE_PREFIX=\"${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" && bash build.sh --config no-tty -c dbg --config python --config test-binaries"] RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10/flavor_base/build_run/Dockerfile index f701d51..1c31859 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/build_run/Dockerfile @@ -27,7 +27,7 @@ COPY exaudfclient/ /exaudfclient/ RUN exaslpm export-variables --out-file /env WORKDIR /exaudfclient/ -RUN ["/bin/bash", "-c", "source /env && bash build.sh --config no-tty --config optimize --config python --config fast-binary"] +RUN ["/bin/bash", "-c", "source /env && export PROTOBUF_LIBRARY_PREFIX=\"${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" PROTOBUF_INCLUDE_PREFIX=\"${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" ZMQ_LIBRARY_PREFIX=\"${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" ZMQ_INCLUDE_PREFIX=\"${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" && bash build.sh --config no-tty --config optimize --config python --config fast-binary"] RUN cp -r -L bazel-bin/* /exaudf RUN rm -r /root/.cache/bazel diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile index 7e4b36d..a4929b7 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile @@ -12,7 +12,12 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && \ + export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ + ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ + ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile index f2b5891..89bf464 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile @@ -30,7 +30,7 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN ["/bin/bash", "-c", "source /env && bash build.sh --config no-tty -c dbg --config python --config test-binaries"] +RUN ["/bin/bash", "-c", "source /env && export PROTOBUF_LIBRARY_PREFIX=\"${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" PROTOBUF_INCLUDE_PREFIX=\"${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" ZMQ_LIBRARY_PREFIX=\"${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" ZMQ_INCLUDE_PREFIX=\"${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" && bash build.sh --config no-tty -c dbg --config python --config test-binaries"] RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12/flavor_base/build_run/Dockerfile index a22c21d..24fbf1b 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/build_run/Dockerfile @@ -26,7 +26,7 @@ RUN mkdir /exaudfclient /exaudf COPY exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN ["/bin/bash", "-c", "source /env && bash build.sh --config no-tty --config optimize --config python --config fast-binary"] +RUN ["/bin/bash", "-c", "source /env && export PROTOBUF_LIBRARY_PREFIX=\"${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" PROTOBUF_INCLUDE_PREFIX=\"${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" ZMQ_LIBRARY_PREFIX=\"${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" ZMQ_INCLUDE_PREFIX=\"${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" && bash build.sh --config no-tty --config optimize --config python --config fast-binary"] RUN cp -r -L bazel-bin/* /exaudf RUN rm -r /root/.cache/bazel diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile index 7e4b36d..a4929b7 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile @@ -12,7 +12,12 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && \ + export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ + ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ + ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ + ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base From e852f917317b6f0e666a7535ec3914f6c6d627df Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Mon, 31 Aug 2026 19:32:25 +0530 Subject: [PATCH 07/32] Add Git to flavor build dependencies --- .../flavor_base/packages.yml | 1 + .../flavor_base/packages.yml | 1 + .../flavor_base/packages.yml | 1 + flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml | 1 + .../flavor_base/packages.yml | 1 + flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml | 1 + flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml | 1 + 7 files changed, 7 insertions(+) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml index e948dec..d773cce 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml @@ -6,6 +6,7 @@ build_steps: channels: - conda-forge packages: + - name: git - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml index c835ece..61a144a 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml @@ -6,6 +6,7 @@ build_steps: channels: - conda-forge packages: + - name: git - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml index 1789e61..aa0c374 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml @@ -6,6 +6,7 @@ build_steps: channels: - conda-forge packages: + - name: git - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml index 2219ef1..c67c0b5 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml @@ -23,6 +23,7 @@ build_steps: - name: install_apt_packages apt: packages: + - name: git - name: coreutils version: 8.32-4.1ubuntu* - name: locales diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml index 38982d5..409ac1b 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml @@ -6,6 +6,7 @@ build_steps: channels: - conda-forge packages: + - name: git - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml index 91eeafd..f9a3aec 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml @@ -4,6 +4,7 @@ build_steps: - name: install_apt_packages apt: packages: + - name: git - name: coreutils version: 9.4-3ubuntu* - name: tar diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml index c835ece..61a144a 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml @@ -6,6 +6,7 @@ build_steps: channels: - conda-forge packages: + - name: git - name: protobuf version: =7.35.1 - name: pcre From 76797682e8e011720688ba48b63b146c24e5f2d7 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Mon, 31 Aug 2026 21:20:51 +0530 Subject: [PATCH 08/32] pinned git versions --- .../flavor_base/packages.yml | 1 + .../flavor_base/packages.yml | 1 + .../flavor_base/packages.yml | 1 + flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml | 1 + .../flavor_base/packages.yml | 1 + flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml | 1 + flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml | 1 + 7 files changed, 7 insertions(+) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml index d773cce..36d74f8 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml @@ -7,6 +7,7 @@ build_steps: - conda-forge packages: - name: git + version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml index 61a144a..82347dd 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml @@ -7,6 +7,7 @@ build_steps: - conda-forge packages: - name: git + version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml index aa0c374..9bcc5d7 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml @@ -7,6 +7,7 @@ build_steps: - conda-forge packages: - name: git + version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml index c67c0b5..102a54d 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml @@ -24,6 +24,7 @@ build_steps: apt: packages: - name: git + version: 1:2.34.1-1ubuntu* - name: coreutils version: 8.32-4.1ubuntu* - name: locales diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml index 409ac1b..6f4e26e 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml @@ -7,6 +7,7 @@ build_steps: - conda-forge packages: - name: git + version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml index f9a3aec..c6a744f 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml @@ -5,6 +5,7 @@ build_steps: apt: packages: - name: git + version: 1:2.43.0-1ubuntu* - name: coreutils version: 9.4-3ubuntu* - name: tar diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml index 61a144a..82347dd 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml @@ -7,6 +7,7 @@ build_steps: - conda-forge packages: - name: git + version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre From 359bdf6282d3b26906976b1371e4af9cdea5d5f9 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 11:16:39 +0530 Subject: [PATCH 09/32] Install Git outside Conda dependency resolution --- .../flavor_base/packages.yml | 9 +++++++-- .../flavor_base/packages.yml | 9 +++++++-- .../flavor_base/packages.yml | 9 +++++++-- .../flavor_base/packages.yml | 9 +++++++-- flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml | 9 +++++++-- 5 files changed, 35 insertions(+), 10 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml index 36d74f8..6d16bb9 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml @@ -1,13 +1,18 @@ build_steps: - name: build_deps phases: + - name: install_apt_packages + apt: + packages: + - name: git + version: 1:2.34.1-1ubuntu* + validation_cfg: + version_mandatory: true - name: install_conda_packages conda: channels: - conda-forge packages: - - name: git - version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml index 82347dd..3c61ed7 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml @@ -1,13 +1,18 @@ build_steps: - name: build_deps phases: + - name: install_apt_packages + apt: + packages: + - name: git + version: 1:2.34.1-1ubuntu* + validation_cfg: + version_mandatory: true - name: install_conda_packages conda: channels: - conda-forge packages: - - name: git - version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml index 9bcc5d7..257174b 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml @@ -1,13 +1,18 @@ build_steps: - name: build_deps phases: + - name: install_apt_packages + apt: + packages: + - name: git + version: 1:2.34.1-1ubuntu* + validation_cfg: + version_mandatory: true - name: install_conda_packages conda: channels: - conda-forge packages: - - name: git - version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml index 6f4e26e..a6a5e29 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml @@ -1,13 +1,18 @@ build_steps: - name: build_deps phases: + - name: install_apt_packages + apt: + packages: + - name: git + version: 1:2.43.0-1ubuntu* + validation_cfg: + version_mandatory: true - name: install_conda_packages conda: channels: - conda-forge packages: - - name: git - version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml index 82347dd..3c61ed7 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml @@ -1,13 +1,18 @@ build_steps: - name: build_deps phases: + - name: install_apt_packages + apt: + packages: + - name: git + version: 1:2.34.1-1ubuntu* + validation_cfg: + version_mandatory: true - name: install_conda_packages conda: channels: - conda-forge packages: - - name: git - version: =2.49.0 - name: protobuf version: =7.35.1 - name: pcre From fd877e45d6cdd3a4b5adc86e43b40b9f13202a59 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 12:29:59 +0530 Subject: [PATCH 10/32] Use Noble Git version for Python 3.12 CUDA flavor --- .../flavor_base/packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml index 3c61ed7..392ef06 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml @@ -5,7 +5,7 @@ build_steps: apt: packages: - name: git - version: 1:2.34.1-1ubuntu* + version: 1:2.43.0-1ubuntu* validation_cfg: version_mandatory: true - name: install_conda_packages From ed5eda5fcc353327eb9cbc3c58eb271be46504ce Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 12:47:58 +0530 Subject: [PATCH 11/32] Fix Bazel upstream module and Noble Git dependency --- exaudfclient/MODULE.bazel | 2 ++ exaudfclient/patches/udf_runner_cpp_build.patch | 10 ++++++++++ flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 exaudfclient/patches/udf_runner_cpp_build.patch diff --git a/exaudfclient/MODULE.bazel b/exaudfclient/MODULE.bazel index 72dee0a..6f46f46 100644 --- a/exaudfclient/MODULE.bazel +++ b/exaudfclient/MODULE.bazel @@ -6,6 +6,8 @@ git_override( remote = "https://github.com/exasol/udf-runner-cpp.git", commit = "b3a8c204a2555b373c66110d5e8301a374b32a6a", strip_prefix = "udf-runner-cpp/v1/base", + patches = ["//:patches/udf_runner_cpp_build.patch"], + patch_args = ["-p0"], ) bazel_dep(name = "rules_cc", version = "0.2.22") bazel_dep(name = "rules_shell", version = "0.8.0") diff --git a/exaudfclient/patches/udf_runner_cpp_build.patch b/exaudfclient/patches/udf_runner_cpp_build.patch new file mode 100644 index 0000000..7b560d2 --- /dev/null +++ b/exaudfclient/patches/udf_runner_cpp_build.patch @@ -0,0 +1,10 @@ +--- BUILD ++++ BUILD +@@ -8,6 +8,7 @@ exports_files(["filter_swig_code.py", "build_integrated.py", + "replace_swig_import_helper.py"]) + + load("//:variables.bzl", "VM_ENABLED_DEFINES") ++load("@rules_cc//cc:defs.bzl", "cc_library") + + config_setting( + name = "benchmark", diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml index 3c61ed7..392ef06 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml @@ -5,7 +5,7 @@ build_steps: apt: packages: - name: git - version: 1:2.34.1-1ubuntu* + version: 1:2.43.0-1ubuntu* validation_cfg: version_mandatory: true - name: install_conda_packages From 63521fb3f9c7336d63facd098ed7a05fe3960ae6 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 12:52:03 +0530 Subject: [PATCH 12/32] Expose rules_cc to patched upstream module --- exaudfclient/patches/udf_runner_cpp_build.patch | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/exaudfclient/patches/udf_runner_cpp_build.patch b/exaudfclient/patches/udf_runner_cpp_build.patch index 7b560d2..abc8d8c 100644 --- a/exaudfclient/patches/udf_runner_cpp_build.patch +++ b/exaudfclient/patches/udf_runner_cpp_build.patch @@ -8,3 +8,9 @@ config_setting( name = "benchmark", + +--- MODULE.bazel ++++ MODULE.bazel +@@ -1,1 +1,2 @@ + module(name="exaudfclient_base", version = "1.0") ++bazel_dep(name = "rules_cc", version = "0.2.22") From 52667905114a8226519a67bad125eb013547f7d5 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 13:30:47 +0530 Subject: [PATCH 13/32] Load cc_binary in upstream runner module --- exaudfclient/patches/udf_runner_cpp_build.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exaudfclient/patches/udf_runner_cpp_build.patch b/exaudfclient/patches/udf_runner_cpp_build.patch index abc8d8c..a327d95 100644 --- a/exaudfclient/patches/udf_runner_cpp_build.patch +++ b/exaudfclient/patches/udf_runner_cpp_build.patch @@ -4,7 +4,7 @@ "replace_swig_import_helper.py"]) load("//:variables.bzl", "VM_ENABLED_DEFINES") -+load("@rules_cc//cc:defs.bzl", "cc_library") ++load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") config_setting( name = "benchmark", From 54dda984eff0c123dc4b6b78324b6efbba176ded Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 14:08:07 +0530 Subject: [PATCH 14/32] Load Bazel C++ rules in upstream packages --- exaudfclient/patches/udf_runner_cpp_build.patch | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/exaudfclient/patches/udf_runner_cpp_build.patch b/exaudfclient/patches/udf_runner_cpp_build.patch index a327d95..c167041 100644 --- a/exaudfclient/patches/udf_runner_cpp_build.patch +++ b/exaudfclient/patches/udf_runner_cpp_build.patch @@ -14,3 +14,15 @@ @@ -1,1 +1,2 @@ module(name="exaudfclient_base", version = "1.0") +bazel_dep(name = "rules_cc", version = "0.2.22") + +--- exaudflib/BUILD ++++ exaudflib/BUILD +@@ -4,1 +4,2 @@ + load("//:variables.bzl", "VM_ENABLED_DEFINES") ++load("@rules_cc//cc:defs.bzl", "cc_library") + +--- exa_udfclient_binary_common/BUILD ++++ exa_udfclient_binary_common/BUILD +@@ -1,1 +1,2 @@ + package(default_visibility = ["//visibility:public"]) ++load("@rules_cc//cc:defs.bzl", "cc_library") From e4e3591d8e40d6ca75632f0fa7770cefb081b7a4 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 14:12:55 +0530 Subject: [PATCH 15/32] Load Bazel C++ rules in all upstream packages --- .../patches/udf_runner_cpp_build.patch | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/exaudfclient/patches/udf_runner_cpp_build.patch b/exaudfclient/patches/udf_runner_cpp_build.patch index c167041..f987552 100644 --- a/exaudfclient/patches/udf_runner_cpp_build.patch +++ b/exaudfclient/patches/udf_runner_cpp_build.patch @@ -26,3 +26,51 @@ @@ -1,1 +1,2 @@ package(default_visibility = ["//visibility:public"]) +load("@rules_cc//cc:defs.bzl", "cc_library") + +--- exaudflib/test/BUILD ++++ exaudflib/test/BUILD +@@ -1,1 +1,2 @@ ++load("@rules_cc//cc:defs.bzl", "cc_test") + cc_test( + +--- script_options_parser/BUILD ++++ script_options_parser/BUILD +@@ -1,1 +1,2 @@ + package(default_visibility = ["//visibility:public"]) ++load("@rules_cc//cc:defs.bzl", "cc_library") + +--- script_options_parser/ctpg/BUILD ++++ script_options_parser/ctpg/BUILD +@@ -1,1 +1,2 @@ + package(default_visibility = ["//visibility:public"]) ++load("@rules_cc//cc:defs.bzl", "cc_library") + +--- script_options_parser/ctpg/test/BUILD ++++ script_options_parser/ctpg/test/BUILD +@@ -1,1 +1,2 @@ ++load("@rules_cc//cc:defs.bzl", "cc_test") + cc_test( + +--- script_options_parser/legacy/BUILD ++++ script_options_parser/legacy/BUILD +@@ -1,1 +1,2 @@ + package(default_visibility = ["//visibility:public"]) ++load("@rules_cc//cc:defs.bzl", "cc_library") + +--- script_options_parser/legacy/test/BUILD ++++ script_options_parser/legacy/test/BUILD +@@ -1,1 +1,2 @@ ++load("@rules_cc//cc:defs.bzl", "cc_test") + cc_test( + +--- swig_factory/BUILD ++++ swig_factory/BUILD +@@ -1,1 +1,2 @@ + package(default_visibility = ["//visibility:public"]) ++load("@rules_cc//cc:defs.bzl", "cc_library") + +--- utils/BUILD ++++ utils/BUILD +@@ -2,1 +2,2 @@ + package(default_visibility = ["//visibility:public"]) ++load("@rules_cc//cc:defs.bzl", "cc_library") From bc3ce87bd9072052d16063057e7c98364d16fa8d Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 17:23:25 +0530 Subject: [PATCH 16/32] remove prints --- .../flavor_base/base_test_build_run/Dockerfile | 3 +-- .../flavor_base/base_test_build_run/Dockerfile | 3 +-- .../flavor_base/base_test_build_run/Dockerfile | 3 +-- .../flavor_base/base_test_build_run/Dockerfile | 3 +-- .../flavor_base/base_test_build_run/Dockerfile | 3 +-- .../flavor_base/base_test_build_run/Dockerfile | 3 +-- 6 files changed, 6 insertions(+), 12 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile index a4929b7..c318963 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -27,6 +27,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ - && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile index 8d208f5..f9d3b7e 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile @@ -28,6 +28,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ - && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile index 89bf464..40a3a4b 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile @@ -40,6 +40,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ - && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile index a4929b7..c318963 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile @@ -27,6 +27,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ - && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile index 89bf464..40a3a4b 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile @@ -40,6 +40,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ - && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile index a4929b7..c318963 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile @@ -27,6 +27,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ - && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. From 4ce5fe3e2920d49b15f8975df74cda143fdc30b2 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 17:24:10 +0530 Subject: [PATCH 17/32] python cpp tests not needed --- .github/workflows/check_bazel_tests.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/check_bazel_tests.yml b/.github/workflows/check_bazel_tests.yml index 78d0594..319825e 100644 --- a/.github/workflows/check_bazel_tests.yml +++ b/.github/workflows/check_bazel_tests.yml @@ -20,11 +20,6 @@ jobs: - name: Install UDF Client Dependencies run: | sudo bash scripts/installUdfClientDeps.sh "$UDF_CLIENT_ENV_FILE" - - name: Build - run: | - source "$UDF_CLIENT_ENV_FILE" - bazel build --lockfile_mode=off --config no-tty -c dbg --config python --config fast-binary --verbose_failures - working-directory: ./exaudfclient/ tests: runs-on: ubuntu-24.04 From 4501d62a78b21385067ee4c1d731155bb6b2c2f4 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 17:39:49 +0530 Subject: [PATCH 18/32] remove unnecessary exports --- .../flavor_base/base_test_build_run/Dockerfile | 7 +------ .../flavor_base/build_run/Dockerfile | 7 +------ .../flavor_base/base_test_build_run/Dockerfile | 7 +------ .../flavor_base/build_run/Dockerfile | 7 +------ .../flavor_base/base_test_build_run/Dockerfile | 7 +------ .../flavor_base/build_run/Dockerfile | 7 +------ .../flavor_base/base_test_build_run/Dockerfile | 7 +------ .../flavor_base/base_test_build_run/Dockerfile | 7 +------ 8 files changed, 8 insertions(+), 48 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile index c318963..a812477 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -12,12 +12,7 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && \ - export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ - ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ - ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/build_run/Dockerfile index 2309c69..6ae21ce 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/build_run/Dockerfile @@ -7,12 +7,7 @@ RUN exaslpm export-variables --out-file /env WORKDIR /exaudfclient/ -RUN source /env && \ - export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ - ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ - ./build.sh --config no-tty --config optimize --config python --config slow-wrapper --config fix_conda_ar_tool +RUN source /env && ./build.sh --config no-tty --config optimize --config python --config slow-wrapper --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile index 556db6f..d37d648 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -13,12 +13,7 @@ COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && \ - export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ - ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ - ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/build_run/Dockerfile index 928e8a6..ce52b90 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/build_run/Dockerfile @@ -7,12 +7,7 @@ RUN exaslpm export-variables --out-file /env WORKDIR /exaudfclient/ -RUN source /env && \ - export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ - ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ - ./build.sh --config no-tty --config optimize --config python --config slow-wrapper --config fix_conda_ar_tool +RUN source /env && ./build.sh --config no-tty --config optimize --config python --config slow-wrapper --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile index f9d3b7e..8c2cc00 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/base_test_build_run/Dockerfile @@ -13,12 +13,7 @@ COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ # We need to build with optimize here, because the debug build fails to run with a runtime linking error regarding protobuf -RUN source /env && \ - export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ - ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ - ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/build_run/Dockerfile index 37cfd87..2e31703 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/build_run/Dockerfile @@ -7,12 +7,7 @@ COPY exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && \ - export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ - ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ - ./build.sh --config no-tty --config optimize --config python --config fast-binary --config fix_conda_ar_tool +RUN source /env && ./build.sh --config no-tty --config optimize --config python --config fast-binary --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile index c318963..a812477 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/base_test_build_run/Dockerfile @@ -12,12 +12,7 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && \ - export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ - ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ - ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile index c318963..a812477 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/base_test_build_run/Dockerfile @@ -12,12 +12,7 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN source /env && \ - export PROTOBUF_LIBRARY_PREFIX="${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - PROTOBUF_INCLUDE_PREFIX="${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" \ - ZMQ_LIBRARY_PREFIX="${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}" \ - ZMQ_INCLUDE_PREFIX="${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}" && \ - ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool +RUN source /env && ./build.sh --config no-tty -c dbg --config python --config test-binaries --config fix_conda_ar_tool RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base From a9ef91f4a0b87a55411f4a1781f7dccf405f09ac Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 18:07:21 +0530 Subject: [PATCH 19/32] lets have no mandatory versions and version pinning --- .../flavor_base/packages.yml | 30 +++++------ .../packages.yml | 36 ++++++------- .../flavor_base/packages.yml | 30 +++++------ .../packages.yml | 38 +++++++------- .../flavor_base/packages.yml | 30 +++++------ .../packages.yml | 32 ++++++------ .../flavor_base/packages.yml | 36 ++++++------- .../packages.yml | 30 +++++------ .../flavor_base/packages.yml | 30 +++++------ .../packages.yml | 34 ++++++------ .../flavor_base/packages.yml | 34 ++++++------ .../packages.yml | 30 +++++------ .../flavor_base/packages.yml | 30 +++++------ flavors/test-Exasol-8-cuda-ml/packages.yml | 52 +++++++++---------- 14 files changed, 236 insertions(+), 236 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml index 6d16bb9..b51494a 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml @@ -5,7 +5,7 @@ build_steps: apt: packages: - name: git - version: 1:2.34.1-1ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: install_conda_packages @@ -14,19 +14,19 @@ build_steps: - conda-forge packages: - name: protobuf - version: =7.35.1 + version: =* - name: pcre - version: '=8.45' + version: =* - name: bazel - version: =9.2.0 + version: =* - name: make - version: '=4.3' + version: =* - name: chrpath - version: '=0.16' + version: =* - name: gxx - version: =13.4.0 + version: =* - name: gcc - version: =13.4.0 + version: =* binary: Mamba variables: PROTOBUF_BIN: '$MAMBA_ROOT_PREFIX/bin/protoc' @@ -44,17 +44,17 @@ build_steps: apt: packages: - name: gdb - version: 12.1-0ubuntu* + version: '*' - name: valgrind - version: 1:3.18.1-1ubuntu* + version: '*' - name: gdbserver - version: 12.1-0ubuntu* + version: '*' - name: binutils - version: 2.38-4ubuntu* + version: '*' - name: patchelf - version: 0.14.3-1 + version: '*' - name: strace - version: 5.16-0ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: security_scan @@ -75,4 +75,4 @@ build_steps: - name: trivy validation_cfg: version_mandatory: false -version: 1.0.0 +version: '*' diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml index ec542ce..fb8ee5a 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml @@ -5,17 +5,17 @@ build_steps: apt: packages: - name: coreutils - version: 8.32-4.1ubuntu* + version: '*' - name: locales - version: 2.35-0ubuntu* + version: '*' - name: curl - version: 7.81.0-1ubuntu* + version: '*' - name: ca-certificates - version: 20260601~22.04.1 + version: '*' - name: bzip2 - version: 1.0.8-5build1 + version: '*' - name: libxml2 - version: 2.9.13+dfsg-1ubuntu* + version: '*' - name: install_micromamba tools: micromamba: @@ -33,13 +33,13 @@ build_steps: - conda-forge packages: - name: libprotobuf - version: =7.35.1 + version: =* - name: zeromq - version: =4.3.5 + version: =* - name: nss - version: '=3.118' + version: =* - name: cppzmq - version: =4.11.0 + version: =* binary: Micromamba variables: PROTOBUF_LIBRARY_PREFIX: $MAMBA_ROOT_PREFIX/lib @@ -61,19 +61,19 @@ build_steps: - nvidia packages: - name: python - version: =3.10.20 + version: =* - name: numpy - version: =2.2.6 + version: =* - name: pandas - version: =2.3.3 + version: =* - name: pyarrow - version: =25.0.0 + version: =* - name: cuda-toolkit - version: =13.3.1 + version: =* - name: libarrow - version: =25.0.0=*_cuda + version: =*=*_cuda - name: mamba - version: =2.8.1 + version: =* binary: Micromamba variables: PYTHON3_PREFIX: $MAMBA_ROOT_PREFIX @@ -90,7 +90,7 @@ build_steps: apt: packages: - name: tzdata - version: 2026* + version: '*' - name: install_conda_packages conda: channels: diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml index 392ef06..b51494a 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml @@ -5,7 +5,7 @@ build_steps: apt: packages: - name: git - version: 1:2.43.0-1ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: install_conda_packages @@ -14,19 +14,19 @@ build_steps: - conda-forge packages: - name: protobuf - version: =7.35.1 + version: =* - name: pcre - version: '=8.45' + version: =* - name: bazel - version: =9.2.0 + version: =* - name: make - version: =4.4.1 + version: =* - name: chrpath - version: '=0.16' + version: =* - name: gxx - version: =13.4.0 + version: =* - name: gcc - version: =13.4.0 + version: =* binary: Mamba variables: PROTOBUF_BIN: '$MAMBA_ROOT_PREFIX/bin/protoc' @@ -44,17 +44,17 @@ build_steps: apt: packages: - name: gdb - version: 15.0.50.20240403-0ubuntu* + version: '*' - name: valgrind - version: 1:3.22.0-0ubuntu* + version: '*' - name: gdbserver - version: 15.0.50.20240403-0ubuntu* + version: '*' - name: binutils - version: 2.42-4ubuntu* + version: '*' - name: patchelf - version: 0.18.0-1.1build1 + version: '*' - name: strace - version: 6.8-0ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: security_scan @@ -75,4 +75,4 @@ build_steps: - name: trivy validation_cfg: version_mandatory: false -version: 1.0.0 +version: '*' diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml index 6487624..f50d292 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml @@ -5,19 +5,19 @@ build_steps: apt: packages: - name: coreutils - version: 9.4-3ubuntu* + version: '*' - name: adduser - version: 3.137ubuntu* + version: '*' - name: locales - version: 2.39-0ubuntu* + version: '*' - name: curl - version: 8.5.0-2ubuntu* + version: '*' - name: ca-certificates - version: '20260601~24.04.1' + version: '*' - name: bzip2 - version: 1.0.8-5.1build0.1 + version: '*' - name: libxml2 - version: 2.9.14+dfsg-1.3ubuntu* + version: '*' - name: install_micromamba tools: micromamba: @@ -35,13 +35,13 @@ build_steps: - conda-forge packages: - name: libprotobuf - version: =7.35.1 + version: =* - name: zeromq - version: =4.3.5 + version: =* - name: nss - version: '=3.118' + version: =* - name: cppzmq - version: =4.11.0 + version: =* binary: Micromamba variables: PROTOBUF_LIBRARY_PREFIX: $MAMBA_ROOT_PREFIX/lib @@ -63,19 +63,19 @@ build_steps: - nvidia packages: - name: python - version: =3.12.13 + version: =* - name: numpy - version: =2.5.1 + version: =* - name: pandas - version: =2.3.3 + version: =* - name: pyarrow - version: =25.0.0 + version: =* - name: libarrow - version: =25.0.0=*_cuda + version: =*=*_cuda - name: mamba - version: =2.8.1 + version: =* - name: cuda-toolkit - version: =13.3.1 + version: =* binary: Micromamba variables: PYTHON3_PREFIX: $MAMBA_ROOT_PREFIX @@ -92,7 +92,7 @@ build_steps: apt: packages: - name: tzdata - version: 2026* + version: '*' - name: install_conda_packages conda: channels: diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml index 257174b..a525d88 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml @@ -5,7 +5,7 @@ build_steps: apt: packages: - name: git - version: 1:2.34.1-1ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: install_conda_packages @@ -14,19 +14,19 @@ build_steps: - conda-forge packages: - name: protobuf - version: =7.35.1 + version: =* - name: pcre - version: '=8.45' + version: =* - name: bazel - version: =9.2.0 + version: =* - name: gxx - version: =12.4.0 + version: =* - name: gcc - version: =12.4.0 + version: =* - name: make - version: '=4.3' + version: =* - name: chrpath - version: '=0.16' + version: =* binary: Mamba variables: PROTOBUF_BIN: /opt/conda/bin/protoc @@ -44,17 +44,17 @@ build_steps: apt: packages: - name: gdb - version: 12.1-0ubuntu* + version: '*' - name: valgrind - version: 1:3.18.1-1ubuntu* + version: '*' - name: gdbserver - version: 12.1-0ubuntu* + version: '*' - name: binutils - version: 2.38-4ubuntu* + version: '*' - name: patchelf - version: 0.14.3-1 + version: '*' - name: strace - version: 5.16-0ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: security_scan @@ -75,4 +75,4 @@ build_steps: - name: trivy validation_cfg: version_mandatory: false -version: 1.0.0 +version: '*' diff --git a/flavors/template-Exasol-all-python-3.10-conda/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/packages.yml index 8910fab..2ef5291 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/packages.yml @@ -5,17 +5,17 @@ build_steps: apt: packages: - name: coreutils - version: 8.32-4.1ubuntu* + version: '*' - name: locales - version: 2.35-0ubuntu* + version: '*' - name: curl - version: 7.81.0-1ubuntu* + version: '*' - name: ca-certificates - version: 20260601~22.04.1 + version: '*' - name: bzip2 - version: 1.0.8-5build1 + version: '*' - name: libxml2 - version: 2.9.13+dfsg-1ubuntu* + version: '*' - name: install_micromamba tools: micromamba: @@ -33,13 +33,13 @@ build_steps: - conda-forge packages: - name: libprotobuf - version: =7.35.1 + version: =* - name: zeromq - version: =4.3.5 + version: =* - name: nss - version: '=3.118' + version: =* - name: cppzmq - version: =4.11.0 + version: =* binary: Micromamba variables: PROTOBUF_LIBRARY_PREFIX: $MAMBA_ROOT_PREFIX/lib @@ -56,15 +56,15 @@ build_steps: - conda-forge packages: - name: python - version: =3.10.20 + version: =* - name: numpy - version: =2.2.6 + version: =* - name: pandas - version: =2.3.3 + version: =* - name: pyarrow - version: =25.0.0 + version: =* - name: mamba - version: =2.8.1 + version: =* binary: Micromamba variables: PYTHON3_PREFIX: $MAMBA_ROOT_PREFIX @@ -81,7 +81,7 @@ build_steps: apt: packages: - name: tzdata - version: 2026* + version: '*' - name: install_conda_packages conda: channels: diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml index 102a54d..7d61142 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/packages.yml @@ -5,17 +5,17 @@ build_steps: apt: packages: - name: gdb - version: 12.1-0ubuntu* + version: '*' - name: valgrind - version: 1:3.18.1-1ubuntu* + version: '*' - name: gdbserver - version: 12.1-0ubuntu* + version: '*' - name: binutils - version: 2.38-4ubuntu* + version: '*' - name: patchelf - version: 0.14.3-1 + version: '*' - name: strace - version: 5.16-0ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: build_deps @@ -24,27 +24,27 @@ build_steps: apt: packages: - name: git - version: 1:2.34.1-1ubuntu* + version: '*' - name: coreutils - version: 8.32-4.1ubuntu* + version: '*' - name: locales - version: 2.35-0ubuntu* + version: '*' - name: tar - version: 1.34+dfsg-1ubuntu* + version: '*' - name: curl - version: 7.81.0-1ubuntu* + version: '*' - name: openjdk-11-jdk-headless - version: 11.0.32+9-1ubuntu* + version: '*' - name: ca-certificates - version: 20260601~22.04.1 + version: '*' - name: build-essential - version: 12.9ubuntu* + version: '*' - name: libpcre3-dev - version: 2:8.39-13ubuntu* + version: '*' - name: protobuf-compiler - version: 3.12.4-1ubuntu* + version: '*' - name: chrpath - version: 0.16-2 + version: '*' variables: PROTOBUF_BIN: /usr/bin/protoc - name: install_bazel @@ -71,4 +71,4 @@ build_steps: - name: trivy validation_cfg: version_mandatory: false -version: 1.0.0 +version: '*' diff --git a/flavors/template-Exasol-all-python-3.10/packages.yml b/flavors/template-Exasol-all-python-3.10/packages.yml index 93ca8ee..9ce82ea 100644 --- a/flavors/template-Exasol-all-python-3.10/packages.yml +++ b/flavors/template-Exasol-all-python-3.10/packages.yml @@ -5,17 +5,17 @@ build_steps: apt: packages: - name: coreutils - version: 8.32-4.1ubuntu* + version: '*' - name: locales - version: 2.35-0ubuntu* + version: '*' - name: libnss-db - version: 2.2.3pre1-6ubuntu* + version: '*' - name: libzmq3-dev - version: 4.3.4-2 + version: '*' - name: libprotobuf-dev - version: 3.12.4-1ubuntu* + version: '*' - name: libssl-dev - version: 3.0.2-0ubuntu* + version: '*' variables: PROTOBUF_LIBRARY_PREFIX: /usr/lib/ PROTOBUF_INCLUDE_PREFIX: /usr/include/ @@ -29,13 +29,13 @@ build_steps: apt: packages: - name: ca-certificates - version: 20260601~22.04.1 + version: '*' - name: python3.10-dev - version: 3.10.12* + version: '*' - name: python3-distutils - version: 3.10.8* + version: '*' - name: curl - version: 7.81.0-1ubuntu* + version: '*' variables: PYTHON3_PREFIX: /usr PYTHON3_VERSION: python3.10 @@ -68,15 +68,15 @@ build_steps: apt: packages: - name: unzip - version: 6.0-26ubuntu* + version: '*' - name: git - version: 1:2.34.1-1ubuntu* + version: '*' - name: libcurl4-openssl-dev - version: 7.81.0-1ubuntu* + version: '*' - name: build-essential - version: 12.9ubuntu* + version: '*' - name: tzdata - version: 2026* + version: '*' validation_cfg: version_mandatory: true - name: flavor_customization diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml index a6a5e29..4b4941b 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml @@ -5,7 +5,7 @@ build_steps: apt: packages: - name: git - version: 1:2.43.0-1ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: install_conda_packages @@ -14,19 +14,19 @@ build_steps: - conda-forge packages: - name: protobuf - version: =7.35.1 + version: =* - name: pcre - version: '=8.45' + version: =* - name: bazel - version: =9.2.0 + version: =* - name: make - version: =4.4.1 + version: =* - name: chrpath - version: '=0.16' + version: =* - name: gxx - version: =15.1.0 + version: =* - name: gcc - version: =15.1.0 + version: =* binary: Mamba variables: PROTOBUF_BIN: '$MAMBA_ROOT_PREFIX/bin/protoc' @@ -44,17 +44,17 @@ build_steps: apt: packages: - name: gdb - version: 15.0.50.20240403-0ubuntu* + version: '*' - name: valgrind - version: 1:3.22.0-0ubuntu* + version: '*' - name: gdbserver - version: 15.0.50.20240403-0ubuntu* + version: '*' - name: binutils - version: 2.42-4ubuntu* + version: '*' - name: patchelf - version: 0.18.0-1.1build1 + version: '*' - name: strace - version: 6.8-0ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: security_scan @@ -75,4 +75,4 @@ build_steps: - name: trivy validation_cfg: version_mandatory: false -version: 1.0.0 +version: '*' diff --git a/flavors/template-Exasol-all-python-3.12-conda/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/packages.yml index 8d62059..808f1bf 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/packages.yml @@ -5,19 +5,19 @@ build_steps: apt: packages: - name: coreutils - version: 9.4-3ubuntu* + version: '*' - name: adduser - version: 3.137ubuntu* + version: '*' - name: locales - version: 2.39-0ubuntu* + version: '*' - name: curl - version: 8.5.0-2ubuntu* + version: '*' - name: ca-certificates - version: '20260601~24.04.1' + version: '*' - name: bzip2 - version: 1.0.8-5.1build0.1 + version: '*' - name: libxml2 - version: 2.9.14+dfsg-1.3ubuntu* + version: '*' - name: install_micromamba tools: micromamba: @@ -35,13 +35,13 @@ build_steps: - conda-forge packages: - name: libprotobuf - version: =7.35.1 + version: =* - name: zeromq - version: =4.3.5 + version: =* - name: nss - version: '=3.118' + version: =* - name: cppzmq - version: =4.11.0 + version: =* binary: Micromamba variables: PROTOBUF_LIBRARY_PREFIX: $MAMBA_ROOT_PREFIX/lib @@ -58,15 +58,15 @@ build_steps: - conda-forge packages: - name: python - version: =3.12.13 + version: =* - name: numpy - version: =2.5.1 + version: =* - name: pandas - version: =2.3.3 + version: =* - name: pyarrow - version: =25.0.0 + version: =* - name: mamba - version: =2.8.1 + version: =* binary: Micromamba variables: PYTHON3_PREFIX: $MAMBA_ROOT_PREFIX @@ -83,7 +83,7 @@ build_steps: apt: packages: - name: tzdata - version: 2026* + version: '*' - name: install_conda_packages conda: channels: diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml index c6a744f..020cfbf 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/packages.yml @@ -5,27 +5,27 @@ build_steps: apt: packages: - name: git - version: 1:2.43.0-1ubuntu* + version: '*' - name: coreutils - version: 9.4-3ubuntu* + version: '*' - name: tar - version: 1.35+dfsg-3ubuntu* + version: '*' - name: curl - version: 8.5.0-2ubuntu* + version: '*' - name: openjdk-17-jdk-headless - version: 17.0.20+8-1~24.04 + version: '*' - name: ca-certificates - version: '20260601~24.04.1' + version: '*' - name: build-essential - version: 12.10ubuntu* + version: '*' - name: libpcre3-dev - version: 2:8.39-15build1 + version: '*' - name: protobuf-compiler - version: 3.21.12-8.2ubuntu* + version: '*' - name: chrpath - version: 0.16-2build1 + version: '*' - name: locales - version: 2.39-0ubuntu* + version: '*' variables: PROTOBUF_BIN: /usr/bin/protoc - name: install_bazel @@ -40,15 +40,15 @@ build_steps: apt: packages: - name: gdb - version: 15.0.50.20240403-0ubuntu* + version: '*' - name: valgrind - version: 1:3.22.0-0ubuntu* + version: '*' - name: binutils - version: 2.42-4ubuntu* + version: '*' - name: patchelf - version: 0.18.0-1.1build1 + version: '*' - name: strace - version: 6.8-0ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: security_scan @@ -69,4 +69,4 @@ build_steps: - name: trivy validation_cfg: version_mandatory: false -version: 1.0.0 +version: '*' diff --git a/flavors/template-Exasol-all-python-3.12/packages.yml b/flavors/template-Exasol-all-python-3.12/packages.yml index 289fb3e..a30128e 100644 --- a/flavors/template-Exasol-all-python-3.12/packages.yml +++ b/flavors/template-Exasol-all-python-3.12/packages.yml @@ -5,11 +5,11 @@ build_steps: apt: packages: - name: ca-certificates - version: '20260601~24.04.1' + version: '*' - name: python3.12-dev - version: 3.12.3-1ubuntu* + version: '*' - name: curl - version: 8.5.0-2ubuntu* + version: '*' variables: PYTHON3_PREFIX: /usr PYTHON3_VERSION: python3.12 @@ -42,21 +42,21 @@ build_steps: apt: packages: - name: coreutils - version: 9.4-3ubuntu* + version: '*' - name: adduser - version: 3.137ubuntu* + version: '*' - name: locales - version: 2.39-0ubuntu* + version: '*' - name: libnss-db - version: 2.2.3pre1-9build3 + version: '*' - name: libzmq3-dev - version: 4.3.5-1build2 + version: '*' - name: cppzmq-dev - version: 4.10.0-1build1 + version: '*' - name: libprotobuf-dev - version: 3.21.12-8.2ubuntu* + version: '*' - name: libssl-dev - version: 3.0.13-0ubuntu* + version: '*' variables: PROTOBUF_LIBRARY_PREFIX: /usr/lib/ PROTOBUF_INCLUDE_PREFIX: /usr/include/ @@ -70,13 +70,13 @@ build_steps: apt: packages: - name: unzip - version: 6.0-28ubuntu* + version: '*' - name: git - version: 1:2.43.0-1ubuntu* + version: '*' - name: libcurl4-openssl-dev - version: 8.5.0-2ubuntu* + version: '*' - name: build-essential - version: 12.10ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: flavor_customization diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml index 392ef06..b51494a 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml @@ -5,7 +5,7 @@ build_steps: apt: packages: - name: git - version: 1:2.43.0-1ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: install_conda_packages @@ -14,19 +14,19 @@ build_steps: - conda-forge packages: - name: protobuf - version: =7.35.1 + version: =* - name: pcre - version: '=8.45' + version: =* - name: bazel - version: =9.2.0 + version: =* - name: make - version: =4.4.1 + version: =* - name: chrpath - version: '=0.16' + version: =* - name: gxx - version: =13.4.0 + version: =* - name: gcc - version: =13.4.0 + version: =* binary: Mamba variables: PROTOBUF_BIN: '$MAMBA_ROOT_PREFIX/bin/protoc' @@ -44,17 +44,17 @@ build_steps: apt: packages: - name: gdb - version: 15.0.50.20240403-0ubuntu* + version: '*' - name: valgrind - version: 1:3.22.0-0ubuntu* + version: '*' - name: gdbserver - version: 15.0.50.20240403-0ubuntu* + version: '*' - name: binutils - version: 2.42-4ubuntu* + version: '*' - name: patchelf - version: 0.18.0-1.1build1 + version: '*' - name: strace - version: 6.8-0ubuntu* + version: '*' validation_cfg: version_mandatory: true - name: security_scan @@ -75,4 +75,4 @@ build_steps: - name: trivy validation_cfg: version_mandatory: false -version: 1.0.0 +version: '*' diff --git a/flavors/test-Exasol-8-cuda-ml/packages.yml b/flavors/test-Exasol-8-cuda-ml/packages.yml index 4bba218..7d53f2a 100644 --- a/flavors/test-Exasol-8-cuda-ml/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/packages.yml @@ -5,19 +5,19 @@ build_steps: apt: packages: - name: coreutils - version: 9.4-3ubuntu* + version: '*' - name: adduser - version: 3.137ubuntu* + version: '*' - name: locales - version: 2.39-0ubuntu* + version: '*' - name: curl - version: 8.5.0-2ubuntu* + version: '*' - name: ca-certificates - version: '20260601~24.04.1' + version: '*' - name: bzip2 - version: 1.0.8-5.1build0.1 + version: '*' - name: libxml2 - version: 2.9.14+dfsg-1.3ubuntu* + version: '*' - name: install_micromamba tools: micromamba: @@ -35,13 +35,13 @@ build_steps: - conda-forge packages: - name: libprotobuf - version: =7.35.1 + version: =* - name: zeromq - version: =4.3.5 + version: =* - name: nss - version: '=3.118' + version: =* - name: cppzmq - version: =4.11.0 + version: =* binary: Micromamba variables: PROTOBUF_LIBRARY_PREFIX: $MAMBA_ROOT_PREFIX/lib @@ -63,17 +63,17 @@ build_steps: - nvidia packages: - name: python - version: =3.12.13 + version: =* - name: numpy - version: =2.4.6 + version: =* - name: pandas - version: =2.3.3 + version: =* - name: pyarrow - version: =25.0.0 + version: =* - name: libarrow - version: =25.0.0=*_cuda + version: =*=*_cuda - name: mamba - version: =2.8.1 + version: =* binary: Micromamba variables: PYTHON3_PREFIX: $MAMBA_ROOT_PREFIX @@ -90,7 +90,7 @@ build_steps: apt: packages: - name: tzdata - version: 2026* + version: '*' - name: install_conda_packages conda: channels: @@ -98,20 +98,20 @@ build_steps: - nvidia packages: - name: cudnn - version: =9.25.0.15 + version: =* - name: cuda-toolkit - version: =13.3.1 + version: =* - name: cuda-nvcc - version: =13.3.73 + version: =* - name: cuda-nvrtc - version: =13.3.33 + version: =* - name: numba - version: =0.66.0 + version: =* - name: numba-cuda - version: =0.30.4 + version: =* - name: pytorch - version: =2.13.0=cuda130_generic_py312_* + version: =*=cuda130_generic_py312_* binary: Mamba validation_cfg: version_mandatory: true -version: 1.0.0 +version: =* From c6852b9ec1af2413bb4c669f9f7116bde4838c08 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 18:23:39 +0530 Subject: [PATCH 20/32] let us be specific about python versions alone --- flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml | 2 +- flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml | 2 +- flavors/template-Exasol-all-python-3.10-conda/packages.yml | 2 +- flavors/template-Exasol-all-python-3.12-conda/packages.yml | 2 +- flavors/test-Exasol-8-cuda-ml/packages.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml index fb8ee5a..aeeaf1d 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml @@ -61,7 +61,7 @@ build_steps: - nvidia packages: - name: python - version: =* + version: =3.10.* - name: numpy version: =* - name: pandas diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml index f50d292..dbbad5d 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml @@ -63,7 +63,7 @@ build_steps: - nvidia packages: - name: python - version: =* + version: =3.12.* - name: numpy version: =* - name: pandas diff --git a/flavors/template-Exasol-all-python-3.10-conda/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/packages.yml index 2ef5291..9c0a209 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/packages.yml @@ -56,7 +56,7 @@ build_steps: - conda-forge packages: - name: python - version: =* + version: =3.10.* - name: numpy version: =* - name: pandas diff --git a/flavors/template-Exasol-all-python-3.12-conda/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/packages.yml index 808f1bf..ac1147b 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/packages.yml @@ -58,7 +58,7 @@ build_steps: - conda-forge packages: - name: python - version: =* + version: =3.12.* - name: numpy version: =* - name: pandas diff --git a/flavors/test-Exasol-8-cuda-ml/packages.yml b/flavors/test-Exasol-8-cuda-ml/packages.yml index 7d53f2a..7474dd4 100644 --- a/flavors/test-Exasol-8-cuda-ml/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/packages.yml @@ -63,7 +63,7 @@ build_steps: - nvidia packages: - name: python - version: =* + version: =3.12.* - name: numpy version: =* - name: pandas From ae9ae83ff95f17de1c41eedc2cf7d1a30b7aeed9 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 18:48:27 +0530 Subject: [PATCH 21/32] let us pin the Bazel to 8.3.1 --- .../flavor_base/packages.yml | 2 +- .../flavor_base/packages.yml | 2 +- .../flavor_base/packages.yml | 2 +- .../flavor_base/packages.yml | 2 +- flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml index b51494a..37810cb 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml @@ -18,7 +18,7 @@ build_steps: - name: pcre version: =* - name: bazel - version: =* + version: =8.3.1 - name: make version: =* - name: chrpath diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml index b51494a..37810cb 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml @@ -18,7 +18,7 @@ build_steps: - name: pcre version: =* - name: bazel - version: =* + version: =8.3.1 - name: make version: =* - name: chrpath diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml index a525d88..67a5b3d 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml @@ -18,7 +18,7 @@ build_steps: - name: pcre version: =* - name: bazel - version: =* + version: =8.3.1 - name: gxx version: =* - name: gcc diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml index 4b4941b..3b1e40c 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml @@ -18,7 +18,7 @@ build_steps: - name: pcre version: =* - name: bazel - version: =* + version: =8.3.1 - name: make version: =* - name: chrpath diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml index b51494a..37810cb 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml @@ -18,7 +18,7 @@ build_steps: - name: pcre version: =* - name: bazel - version: =* + version: =8.3.1 - name: make version: =* - name: chrpath From 89b3394a96c686b2cdf6df7206c311909446551b Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 19:11:58 +0530 Subject: [PATCH 22/32] we need binutils --- .../flavor_base/packages.yml | 2 ++ .../flavor_base/packages.yml | 2 ++ .../flavor_base/packages.yml | 2 ++ .../flavor_base/packages.yml | 2 ++ flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml | 2 ++ 5 files changed, 10 insertions(+) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml index 37810cb..6056912 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml @@ -25,6 +25,8 @@ build_steps: version: =* - name: gxx version: =* + - name: binutils + version: =* - name: gcc version: =* binary: Mamba diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml index 37810cb..6056912 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml @@ -25,6 +25,8 @@ build_steps: version: =* - name: gxx version: =* + - name: binutils + version: =* - name: gcc version: =* binary: Mamba diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml index 67a5b3d..16ded34 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml @@ -25,6 +25,8 @@ build_steps: version: =* - name: make version: =* + - name: binutils + version: =* - name: chrpath version: =* binary: Mamba diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml index 3b1e40c..9ede814 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml @@ -25,6 +25,8 @@ build_steps: version: =* - name: gxx version: =* + - name: binutils + version: =* - name: gcc version: =* binary: Mamba diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml index 37810cb..6056912 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml @@ -25,6 +25,8 @@ build_steps: version: =* - name: gxx version: =* + - name: binutils + version: =* - name: gcc version: =* binary: Mamba From ed93f56ce5b4862ffb9930b55e5c99607f9564d2 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 20:46:16 +0530 Subject: [PATCH 23/32] Removed redundant append that caused protoc syntax errors --- .../flavor_base/base_test_build_run/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile index d37d648..fcfb71f 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/base_test_build_run/Dockerfile @@ -24,6 +24,5 @@ RUN ./test_udfclient.sh /exaudf/exaudfclient_static WORKDIR / RUN mkdir /exasol_emulator COPY emulator/ /exasol_emulator -RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto \ - && printf '%s\n' ' optional exascript_ping ping = 9;' ' optional exascript_single_call_rep call = 10;' '}' >> /exasol_emulator/zmqcontainer.proto +RUN curl -fsSL "https://raw.githubusercontent.com/exasol/udf-runner-cpp/${UDF_RUNNER_CPP_COMMIT}/udf-runner-cpp/v1/base/exaudflib/zmqcontainer.proto" -o /exasol_emulator/zmqcontainer.proto RUN cd /exasol_emulator && protoc zmqcontainer.proto --python_out=. From 50cdb6e28d08c00af774c017009513758f90c268 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Tue, 1 Sep 2026 22:25:04 +0530 Subject: [PATCH 24/32] pinning numpy, pandas and pyarrow --- .../template-Exasol-8-python-3.10-cuda-conda/packages.yml | 6 +++--- .../template-Exasol-8-python-3.12-cuda-conda/packages.yml | 6 +++--- flavors/template-Exasol-all-python-3.10-conda/packages.yml | 6 +++--- flavors/template-Exasol-all-python-3.12-conda/packages.yml | 6 +++--- flavors/test-Exasol-8-cuda-ml/packages.yml | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml index aeeaf1d..b7cb82f 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml @@ -63,11 +63,11 @@ build_steps: - name: python version: =3.10.* - name: numpy - version: =* + version: =2.2.6 - name: pandas - version: =* + version: =2.3.3 - name: pyarrow - version: =* + version: =25.0.0 - name: cuda-toolkit version: =* - name: libarrow diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml index dbbad5d..d3c91d0 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml @@ -65,11 +65,11 @@ build_steps: - name: python version: =3.12.* - name: numpy - version: =* + version: =2.2.6 - name: pandas - version: =* + version: =2.3.3 - name: pyarrow - version: =* + version: =25.0.0 - name: libarrow version: =*=*_cuda - name: mamba diff --git a/flavors/template-Exasol-all-python-3.10-conda/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/packages.yml index 9c0a209..87e3f20 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/packages.yml @@ -58,11 +58,11 @@ build_steps: - name: python version: =3.10.* - name: numpy - version: =* + version: =2.2.6 - name: pandas - version: =* + version: =2.3.3 - name: pyarrow - version: =* + version: =25.0.0 - name: mamba version: =* binary: Micromamba diff --git a/flavors/template-Exasol-all-python-3.12-conda/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/packages.yml index ac1147b..5ab0da2 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/packages.yml @@ -60,11 +60,11 @@ build_steps: - name: python version: =3.12.* - name: numpy - version: =* + version: =2.2.6 - name: pandas - version: =* + version: =2.3.3 - name: pyarrow - version: =* + version: =25.0.0 - name: mamba version: =* binary: Micromamba diff --git a/flavors/test-Exasol-8-cuda-ml/packages.yml b/flavors/test-Exasol-8-cuda-ml/packages.yml index 7474dd4..f9c8fe1 100644 --- a/flavors/test-Exasol-8-cuda-ml/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/packages.yml @@ -65,11 +65,11 @@ build_steps: - name: python version: =3.12.* - name: numpy - version: =* + version: =2.2.6 - name: pandas - version: =* + version: =2.3.3 - name: pyarrow - version: =* + version: =25.0.0 - name: libarrow version: =*=*_cuda - name: mamba From 6753f8b7f71a8507fbb214f1e8e3823a775ddd15 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Wed, 2 Sep 2026 11:42:23 +0530 Subject: [PATCH 25/32] Use compatible PyArrow version for Conda builds --- flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml | 2 +- flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml | 2 +- flavors/template-Exasol-all-python-3.10-conda/packages.yml | 2 +- flavors/template-Exasol-all-python-3.12-conda/packages.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml index b7cb82f..31e0581 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml @@ -67,7 +67,7 @@ build_steps: - name: pandas version: =2.3.3 - name: pyarrow - version: =25.0.0 + version: =24.0.0 - name: cuda-toolkit version: =* - name: libarrow diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml index d3c91d0..33a9f09 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml @@ -69,7 +69,7 @@ build_steps: - name: pandas version: =2.3.3 - name: pyarrow - version: =25.0.0 + version: =24.0.0 - name: libarrow version: =*=*_cuda - name: mamba diff --git a/flavors/template-Exasol-all-python-3.10-conda/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/packages.yml index 87e3f20..3c39bbb 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/packages.yml @@ -62,7 +62,7 @@ build_steps: - name: pandas version: =2.3.3 - name: pyarrow - version: =25.0.0 + version: =24.0.0 - name: mamba version: =* binary: Micromamba diff --git a/flavors/template-Exasol-all-python-3.12-conda/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/packages.yml index 5ab0da2..19bfed4 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/packages.yml @@ -64,7 +64,7 @@ build_steps: - name: pandas version: =2.3.3 - name: pyarrow - version: =25.0.0 + version: =24.0.0 - name: mamba version: =* binary: Micromamba From 8e67d3a02773501b6de2dc16dd8591e78549609d Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Wed, 2 Sep 2026 12:21:46 +0530 Subject: [PATCH 26/32] fiddling around bazel versions --- .../flavor_base/packages.yml | 8 ++++++-- .../template-Exasol-8-python-3.10-cuda-conda/packages.yml | 2 +- .../flavor_base/packages.yml | 8 ++++++-- .../template-Exasol-8-python-3.12-cuda-conda/packages.yml | 2 +- .../flavor_base/packages.yml | 8 ++++++-- .../template-Exasol-all-python-3.10-conda/packages.yml | 2 +- .../flavor_base/packages.yml | 8 ++++++-- .../template-Exasol-all-python-3.12-conda/packages.yml | 2 +- flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml | 8 ++++++-- 9 files changed, 34 insertions(+), 14 deletions(-) diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml index 6056912..d3aa9e6 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/flavor_base/packages.yml @@ -17,8 +17,6 @@ build_steps: version: =* - name: pcre version: =* - - name: bazel - version: =8.3.1 - name: make version: =* - name: chrpath @@ -30,6 +28,12 @@ build_steps: - name: gcc version: =* binary: Mamba + - name: install_bazel + tools: + bazel: + version: '8.3.1' + validation_cfg: + version_mandatory: true variables: PROTOBUF_BIN: '$MAMBA_ROOT_PREFIX/bin/protoc' LD_LIBRARY_PATH: '$LD_LIBRARY_PATH:$MAMBA_ROOT_PREFIX/lib/' diff --git a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml index 31e0581..b7cb82f 100644 --- a/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.10-cuda-conda/packages.yml @@ -67,7 +67,7 @@ build_steps: - name: pandas version: =2.3.3 - name: pyarrow - version: =24.0.0 + version: =25.0.0 - name: cuda-toolkit version: =* - name: libarrow diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml index 6056912..d3aa9e6 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/flavor_base/packages.yml @@ -17,8 +17,6 @@ build_steps: version: =* - name: pcre version: =* - - name: bazel - version: =8.3.1 - name: make version: =* - name: chrpath @@ -30,6 +28,12 @@ build_steps: - name: gcc version: =* binary: Mamba + - name: install_bazel + tools: + bazel: + version: '8.3.1' + validation_cfg: + version_mandatory: true variables: PROTOBUF_BIN: '$MAMBA_ROOT_PREFIX/bin/protoc' LD_LIBRARY_PATH: '$LD_LIBRARY_PATH:$MAMBA_ROOT_PREFIX/lib/' diff --git a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml index 33a9f09..d3c91d0 100644 --- a/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml +++ b/flavors/template-Exasol-8-python-3.12-cuda-conda/packages.yml @@ -69,7 +69,7 @@ build_steps: - name: pandas version: =2.3.3 - name: pyarrow - version: =24.0.0 + version: =25.0.0 - name: libarrow version: =*=*_cuda - name: mamba diff --git a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml index 16ded34..f806aa8 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/flavor_base/packages.yml @@ -17,8 +17,6 @@ build_steps: version: =* - name: pcre version: =* - - name: bazel - version: =8.3.1 - name: gxx version: =* - name: gcc @@ -30,6 +28,12 @@ build_steps: - name: chrpath version: =* binary: Mamba + - name: install_bazel + tools: + bazel: + version: '8.3.1' + validation_cfg: + version_mandatory: true variables: PROTOBUF_BIN: /opt/conda/bin/protoc LD_LIBRARY_PATH: '$LD_LIBRARY_PATH:$MAMBA_ROOT_PREFIX/lib/' diff --git a/flavors/template-Exasol-all-python-3.10-conda/packages.yml b/flavors/template-Exasol-all-python-3.10-conda/packages.yml index 3c39bbb..87e3f20 100644 --- a/flavors/template-Exasol-all-python-3.10-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.10-conda/packages.yml @@ -62,7 +62,7 @@ build_steps: - name: pandas version: =2.3.3 - name: pyarrow - version: =24.0.0 + version: =25.0.0 - name: mamba version: =* binary: Micromamba diff --git a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml index 9ede814..fed4dd7 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/flavor_base/packages.yml @@ -17,8 +17,6 @@ build_steps: version: =* - name: pcre version: =* - - name: bazel - version: =8.3.1 - name: make version: =* - name: chrpath @@ -30,6 +28,12 @@ build_steps: - name: gcc version: =* binary: Mamba + - name: install_bazel + tools: + bazel: + version: '8.3.1' + validation_cfg: + version_mandatory: true variables: PROTOBUF_BIN: '$MAMBA_ROOT_PREFIX/bin/protoc' LD_LIBRARY_PATH: '$LD_LIBRARY_PATH:$MAMBA_ROOT_PREFIX/lib/' diff --git a/flavors/template-Exasol-all-python-3.12-conda/packages.yml b/flavors/template-Exasol-all-python-3.12-conda/packages.yml index 19bfed4..5ab0da2 100644 --- a/flavors/template-Exasol-all-python-3.12-conda/packages.yml +++ b/flavors/template-Exasol-all-python-3.12-conda/packages.yml @@ -64,7 +64,7 @@ build_steps: - name: pandas version: =2.3.3 - name: pyarrow - version: =24.0.0 + version: =25.0.0 - name: mamba version: =* binary: Micromamba diff --git a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml index 6056912..d3aa9e6 100644 --- a/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml +++ b/flavors/test-Exasol-8-cuda-ml/flavor_base/packages.yml @@ -17,8 +17,6 @@ build_steps: version: =* - name: pcre version: =* - - name: bazel - version: =8.3.1 - name: make version: =* - name: chrpath @@ -30,6 +28,12 @@ build_steps: - name: gcc version: =* binary: Mamba + - name: install_bazel + tools: + bazel: + version: '8.3.1' + validation_cfg: + version_mandatory: true variables: PROTOBUF_BIN: '$MAMBA_ROOT_PREFIX/bin/protoc' LD_LIBRARY_PATH: '$LD_LIBRARY_PATH:$MAMBA_ROOT_PREFIX/lib/' From 566b2122b55fd825c8236498d1b69a8da841c72d Mon Sep 17 00:00:00 2001 From: Shankar Date: Wed, 2 Sep 2026 14:45:42 +0530 Subject: [PATCH 27/32] Update exaudfclient/exaudfclient.template.sh Co-authored-by: Torsten Kilias --- exaudfclient/exaudfclient.template.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exaudfclient/exaudfclient.template.sh b/exaudfclient/exaudfclient.template.sh index fffd9a3..7790862 100644 --- a/exaudfclient/exaudfclient.template.sh +++ b/exaudfclient/exaudfclient.template.sh @@ -10,5 +10,5 @@ then export CONDA_DEFAULT_ENV=base export CONDA_PREFIX=/opt/conda export MAMBA_ROOT_PREFIX=$CONDA_PREFIX - export LD_LIBRARY_PATH="$CONDA_PREFIX/cuda-compat/:$LD_LIBRARY_PATH" + export LD_LIBRARY_PATH="$CONDA_PREFIX/cuda-compat/:$LD_LIBRARY_PATH" # Temporary hack for the Cuda ML flavor(s) fi From 8caefe73a7667dcd924a4d885cbb1214af463150 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Wed, 2 Sep 2026 16:28:43 +0530 Subject: [PATCH 28/32] removed redundant exports and brought back pycpp build --- .github/workflows/check_bazel_tests.yml | 6 ++++++ .../flavor_base/base_test_build_run/Dockerfile | 2 +- .../flavor_base/build_run/Dockerfile | 2 +- .../flavor_base/base_test_build_run/Dockerfile | 2 +- .../flavor_base/build_run/Dockerfile | 2 +- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check_bazel_tests.yml b/.github/workflows/check_bazel_tests.yml index 319825e..26c3fcb 100644 --- a/.github/workflows/check_bazel_tests.yml +++ b/.github/workflows/check_bazel_tests.yml @@ -21,6 +21,12 @@ jobs: run: | sudo bash scripts/installUdfClientDeps.sh "$UDF_CLIENT_ENV_FILE" + - name: Build + run: | + source "$UDF_CLIENT_ENV_FILE" + bazel build --lockfile_mode=off --config no-tty -c dbg --config python --config fast-binary --verbose_failures + working-directory: ./exaudfclient/ + tests: runs-on: ubuntu-24.04 strategy: diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile index 40a3a4b..d155d3e 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/base_test_build_run/Dockerfile @@ -30,7 +30,7 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN ["/bin/bash", "-c", "source /env && export PROTOBUF_LIBRARY_PREFIX=\"${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" PROTOBUF_INCLUDE_PREFIX=\"${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" ZMQ_LIBRARY_PREFIX=\"${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" ZMQ_INCLUDE_PREFIX=\"${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" && bash build.sh --config no-tty -c dbg --config python --config test-binaries"] +RUN ["/bin/bash", "-c", "source /env && bash build.sh --config no-tty -c dbg --config python --config test-binaries"] RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.10/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-all-python-3.10/flavor_base/build_run/Dockerfile index 1c31859..f701d51 100644 --- a/flavors/template-Exasol-all-python-3.10/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.10/flavor_base/build_run/Dockerfile @@ -27,7 +27,7 @@ COPY exaudfclient/ /exaudfclient/ RUN exaslpm export-variables --out-file /env WORKDIR /exaudfclient/ -RUN ["/bin/bash", "-c", "source /env && export PROTOBUF_LIBRARY_PREFIX=\"${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" PROTOBUF_INCLUDE_PREFIX=\"${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" ZMQ_LIBRARY_PREFIX=\"${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" ZMQ_INCLUDE_PREFIX=\"${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" && bash build.sh --config no-tty --config optimize --config python --config fast-binary"] +RUN ["/bin/bash", "-c", "source /env && bash build.sh --config no-tty --config optimize --config python --config fast-binary"] RUN cp -r -L bazel-bin/* /exaudf RUN rm -r /root/.cache/bazel diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile index 40a3a4b..d155d3e 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/base_test_build_run/Dockerfile @@ -30,7 +30,7 @@ RUN mkdir /exaudfclient /exaudf COPY /exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN ["/bin/bash", "-c", "source /env && export PROTOBUF_LIBRARY_PREFIX=\"${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" PROTOBUF_INCLUDE_PREFIX=\"${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" ZMQ_LIBRARY_PREFIX=\"${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" ZMQ_INCLUDE_PREFIX=\"${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" && bash build.sh --config no-tty -c dbg --config python --config test-binaries"] +RUN ["/bin/bash", "-c", "source /env && bash build.sh --config no-tty -c dbg --config python --config test-binaries"] RUN cp -r -L bazel-bin/* /exaudf WORKDIR /exaudfclient/base diff --git a/flavors/template-Exasol-all-python-3.12/flavor_base/build_run/Dockerfile b/flavors/template-Exasol-all-python-3.12/flavor_base/build_run/Dockerfile index 24fbf1b..a22c21d 100644 --- a/flavors/template-Exasol-all-python-3.12/flavor_base/build_run/Dockerfile +++ b/flavors/template-Exasol-all-python-3.12/flavor_base/build_run/Dockerfile @@ -26,7 +26,7 @@ RUN mkdir /exaudfclient /exaudf COPY exaudfclient/ /exaudfclient/ WORKDIR /exaudfclient/ -RUN ["/bin/bash", "-c", "source /env && export PROTOBUF_LIBRARY_PREFIX=\"${PROTOBUF_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" PROTOBUF_INCLUDE_PREFIX=\"${PROTOBUF_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" ZMQ_LIBRARY_PREFIX=\"${ZMQ_LIBRARY_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/lib}\" ZMQ_INCLUDE_PREFIX=\"${ZMQ_INCLUDE_PREFIX:-${MAMBA_ROOT_PREFIX:-/usr}/include}\" && bash build.sh --config no-tty --config optimize --config python --config fast-binary"] +RUN ["/bin/bash", "-c", "source /env && bash build.sh --config no-tty --config optimize --config python --config fast-binary"] RUN cp -r -L bazel-bin/* /exaudf RUN rm -r /root/.cache/bazel From f8c31a50b0269b6ca0feb81aa18b18a1c0c05c1d Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Thu, 3 Sep 2026 12:08:16 +0530 Subject: [PATCH 29/32] update the udf-runner-cpp --- exaudfclient/MODULE.bazel | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exaudfclient/MODULE.bazel b/exaudfclient/MODULE.bazel index 6f46f46..c53c089 100644 --- a/exaudfclient/MODULE.bazel +++ b/exaudfclient/MODULE.bazel @@ -4,7 +4,7 @@ bazel_dep(name = "exaudfclient_base", version = "1.0.0") git_override( module_name = "exaudfclient_base", remote = "https://github.com/exasol/udf-runner-cpp.git", - commit = "b3a8c204a2555b373c66110d5e8301a374b32a6a", + commit = "fe4ca609677c556fafb99b2be0501203843d850f", strip_prefix = "udf-runner-cpp/v1/base", patches = ["//:patches/udf_runner_cpp_build.patch"], patch_args = ["-p0"], From 36fd189588ea9d04a179d1ad122857c8fe7241a3 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Thu, 3 Sep 2026 12:17:23 +0530 Subject: [PATCH 30/32] removed the stale patches --- exaudfclient/MODULE.bazel | 2 - .../patches/udf_runner_cpp_build.patch | 76 ------------------- 2 files changed, 78 deletions(-) delete mode 100644 exaudfclient/patches/udf_runner_cpp_build.patch diff --git a/exaudfclient/MODULE.bazel b/exaudfclient/MODULE.bazel index c53c089..84eadd6 100644 --- a/exaudfclient/MODULE.bazel +++ b/exaudfclient/MODULE.bazel @@ -6,8 +6,6 @@ git_override( remote = "https://github.com/exasol/udf-runner-cpp.git", commit = "fe4ca609677c556fafb99b2be0501203843d850f", strip_prefix = "udf-runner-cpp/v1/base", - patches = ["//:patches/udf_runner_cpp_build.patch"], - patch_args = ["-p0"], ) bazel_dep(name = "rules_cc", version = "0.2.22") bazel_dep(name = "rules_shell", version = "0.8.0") diff --git a/exaudfclient/patches/udf_runner_cpp_build.patch b/exaudfclient/patches/udf_runner_cpp_build.patch deleted file mode 100644 index f987552..0000000 --- a/exaudfclient/patches/udf_runner_cpp_build.patch +++ /dev/null @@ -1,76 +0,0 @@ ---- BUILD -+++ BUILD -@@ -8,6 +8,7 @@ exports_files(["filter_swig_code.py", "build_integrated.py", - "replace_swig_import_helper.py"]) - - load("//:variables.bzl", "VM_ENABLED_DEFINES") -+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") - - config_setting( - name = "benchmark", - ---- MODULE.bazel -+++ MODULE.bazel -@@ -1,1 +1,2 @@ - module(name="exaudfclient_base", version = "1.0") -+bazel_dep(name = "rules_cc", version = "0.2.22") - ---- exaudflib/BUILD -+++ exaudflib/BUILD -@@ -4,1 +4,2 @@ - load("//:variables.bzl", "VM_ENABLED_DEFINES") -+load("@rules_cc//cc:defs.bzl", "cc_library") - ---- exa_udfclient_binary_common/BUILD -+++ exa_udfclient_binary_common/BUILD -@@ -1,1 +1,2 @@ - package(default_visibility = ["//visibility:public"]) -+load("@rules_cc//cc:defs.bzl", "cc_library") - ---- exaudflib/test/BUILD -+++ exaudflib/test/BUILD -@@ -1,1 +1,2 @@ -+load("@rules_cc//cc:defs.bzl", "cc_test") - cc_test( - ---- script_options_parser/BUILD -+++ script_options_parser/BUILD -@@ -1,1 +1,2 @@ - package(default_visibility = ["//visibility:public"]) -+load("@rules_cc//cc:defs.bzl", "cc_library") - ---- script_options_parser/ctpg/BUILD -+++ script_options_parser/ctpg/BUILD -@@ -1,1 +1,2 @@ - package(default_visibility = ["//visibility:public"]) -+load("@rules_cc//cc:defs.bzl", "cc_library") - ---- script_options_parser/ctpg/test/BUILD -+++ script_options_parser/ctpg/test/BUILD -@@ -1,1 +1,2 @@ -+load("@rules_cc//cc:defs.bzl", "cc_test") - cc_test( - ---- script_options_parser/legacy/BUILD -+++ script_options_parser/legacy/BUILD -@@ -1,1 +1,2 @@ - package(default_visibility = ["//visibility:public"]) -+load("@rules_cc//cc:defs.bzl", "cc_library") - ---- script_options_parser/legacy/test/BUILD -+++ script_options_parser/legacy/test/BUILD -@@ -1,1 +1,2 @@ -+load("@rules_cc//cc:defs.bzl", "cc_test") - cc_test( - ---- swig_factory/BUILD -+++ swig_factory/BUILD -@@ -1,1 +1,2 @@ - package(default_visibility = ["//visibility:public"]) -+load("@rules_cc//cc:defs.bzl", "cc_library") - ---- utils/BUILD -+++ utils/BUILD -@@ -2,1 +2,2 @@ - package(default_visibility = ["//visibility:public"]) -+load("@rules_cc//cc:defs.bzl", "cc_library") From 55338a6bf50a9dbd3883ad93eda7a89b36b05ccc Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Thu, 3 Sep 2026 12:46:46 +0530 Subject: [PATCH 31/32] remove the tests job; we do it for py a bit later --- .github/workflows/check_bazel_tests.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/check_bazel_tests.yml b/.github/workflows/check_bazel_tests.yml index 26c3fcb..5140d2b 100644 --- a/.github/workflows/check_bazel_tests.yml +++ b/.github/workflows/check_bazel_tests.yml @@ -27,14 +27,6 @@ jobs: bazel build --lockfile_mode=off --config no-tty -c dbg --config python --config fast-binary --verbose_failures working-directory: ./exaudfclient/ - tests: - runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - include: - - test: "@exaudfclient_base//exaudflib/test/..." - name: "exaudflib" steps: - uses: actions/checkout@v6 - name: Install ZMQ From 20e8b4b5819623b1ee0e2bd6ae5675b82367a079 Mon Sep 17 00:00:00 2001 From: "Shankar.KV" Date: Thu, 3 Sep 2026 12:54:01 +0530 Subject: [PATCH 32/32] remove it fully --- .github/workflows/check_bazel_tests.yml | 31 +------------------------ 1 file changed, 1 insertion(+), 30 deletions(-) diff --git a/.github/workflows/check_bazel_tests.yml b/.github/workflows/check_bazel_tests.yml index 5140d2b..680698b 100644 --- a/.github/workflows/check_bazel_tests.yml +++ b/.github/workflows/check_bazel_tests.yml @@ -25,33 +25,4 @@ jobs: run: | source "$UDF_CLIENT_ENV_FILE" bazel build --lockfile_mode=off --config no-tty -c dbg --config python --config fast-binary --verbose_failures - working-directory: ./exaudfclient/ - - steps: - - uses: actions/checkout@v6 - - name: Install ZMQ - run: | - sudo apt-get update - sudo apt-get install -y libzmq3-dev valgrind - - name: Install bazel - run: | - BAZEL_PACKAGE_FILE="bazel_$BAZEL_PACKAGE_VERSION-linux-x86_64.deb" - BAZEL_PACKAGE_URL="https://github.com/bazelbuild/bazel/releases/download/$BAZEL_PACKAGE_VERSION/$BAZEL_PACKAGE_FILE" - curl -L --output /tmp/"$BAZEL_PACKAGE_FILE" "$BAZEL_PACKAGE_URL" - sudo apt install -y "/tmp/$BAZEL_PACKAGE_FILE" - rm "/tmp/$BAZEL_PACKAGE_FILE" - env: - BAZEL_PACKAGE_VERSION: "8.3.1" - - name: Run tests - run: | - bazel test ${{ matrix.additional_args }} ${{ matrix.test }} - working-directory: ./exaudfclient - env: - OPENSSL_LIBRARY_PREFIX: "/usr/lib/x86_64-linux-gnu" - OPENSSL_INCLUDE_PREFIX: "/usr/include/openssl" - - - uses: actions/upload-artifact@v4 - if: failure() - with: - name: "${{ matrix.name }}" - path: /home/runner/.cache/bazel/_bazel_runner/*/execroot/_main/bazel-out/k8-dbg/testlogs/**/test.log + working-directory: ./exaudfclient/ \ No newline at end of file