diff --git a/NOTICE b/NOTICE index 6c93ec79b..18bd86797 100644 --- a/NOTICE +++ b/NOTICE @@ -1,5 +1,5 @@ Apache MADlib -Copyright 2016-2024 The Apache Software Foundation. +Copyright 2016-2025 The Apache Software Foundation. This product includes software developed at The Apache Software Foundation (http://www.apache.org/). diff --git a/methods/kmeans/src/pg_gp/kmeans.c b/methods/kmeans/src/pg_gp/kmeans.c index a9d0cc0d8..015b10203 100644 --- a/methods/kmeans/src/pg_gp/kmeans.c +++ b/methods/kmeans/src/pg_gp/kmeans.c @@ -87,7 +87,7 @@ compute_metric(PGFunction inMetricFn, MemoryContext inMemContext, Datum inVec1, * in execUtils.c */ -#if GP_VERSION_NUM >= 70000 +#if defined(IS_CLOUDBERRY) || GP_VERSION_NUM >= 70000 if(inMemContext->mem_allocated > 50000) #else if(inMemContext->allBytesAlloc - inMemContext->allBytesFreed > 50000) diff --git a/src/bin/madpack b/src/bin/madpack index 66fea1554..fc6a34ac4 100755 --- a/src/bin/madpack +++ b/src/bin/madpack @@ -13,7 +13,7 @@ # 2. Pass all arguments to ../madpack/madpack.py PYTHON_PREFIX="python" -PYTHON_VERSIONS="2.7 2.6 3" +PYTHON_VERSIONS="3" # create absolute path to madpack.py pushd `dirname $0` > /dev/null diff --git a/src/config/Ports.yml b/src/config/Ports.yml index 78327d738..8308a3be0 100644 --- a/src/config/Ports.yml +++ b/src/config/Ports.yml @@ -9,3 +9,6 @@ postgres: greenplum: name: Greenplum DB + +cloudberry: + name: Apache Cloudberry \ No newline at end of file diff --git a/src/library.ver b/src/library.ver index 680928d0d..eb4965edb 100644 --- a/src/library.ver +++ b/src/library.ver @@ -8,6 +8,8 @@ VERS_1.0 { _ZnamRKSt9nothrow_t; # operator new[](unsigned long, std::nothrow_t const&); _ZdaPv; # operator delete[](void*); _ZdaPvRKSt9nothrow_t; # operator delete[](void*, std::nothrow_t const&); + _ZdlPvm ; # operator delete(void*, size_t); + _ZdaPvm ; # operator delete[](void*, size_t); extern "C++" { # diff --git a/src/madpack/madpack.py b/src/madpack/madpack.py index fc4c65374..9ca685057 100755 --- a/src/madpack/madpack.py +++ b/src/madpack/madpack.py @@ -64,7 +64,7 @@ for port in ports: portid_list.append(port) -SUPPORTED_PORTS = ('postgres', 'greenplum') +SUPPORTED_PORTS = ('postgres', 'greenplum', 'cloudberry') # Global variables portid = None # Target port ID (eg: pg90, gp40) @@ -189,7 +189,8 @@ def _run_m4_and_append(schema, maddir_mod_py, module, sqlfile, '-I' + maddir_madpack, sqlfile] if ( (portid == 'postgres') & - (is_rev_gte(get_rev_num(dbver), get_rev_num('14.0'))) ): + (is_rev_gte(get_rev_num(dbver), get_rev_num('14.0'))) or + (portid == 'cloudberry') ): m4args = ['m4', '-P', '-DMADLIB_SCHEMA=' + schema, @@ -370,7 +371,7 @@ def _check_db_port(portid): if portid == 'postgres': if row[0]['version'].lower().find('greenplum') < 0: return True - elif portid == 'greenplum': + elif portid == 'greenplum' or portid == 'cloudberry': return True return False # ------------------------------------------------------------------------------ @@ -1240,6 +1241,7 @@ def create_install_madlib_sqlfile(args, madpack_cmd): def get_madlib_function_drop_str(schema): if ((portid == 'greenplum' and is_rev_gte(get_rev_num(dbver), get_rev_num('7.0'))) or + (portid == 'cloudberry') or (portid == 'postgres')): case_str = """ CASE p.prokind @@ -1343,15 +1345,17 @@ def set_dynamic_library_path_in_database(dbver_split, madlib_library_path): if ((portid == 'greenplum' and is_rev_gte(dbver_split, get_rev_num('7.0'))) or (portid == 'postgres' and is_rev_gte(dbver_split, get_rev_num('13.0')))): libdir = libdir.decode() + else: + libdir = libdir.decode('utf-8') - libdir = libdir.strip()+'/postgresql' + libdir = libdir.strip() + '/postgresql' paths.append(libdir) paths.append(madlib_library_path) dynamic_library_path = ':'.join(paths) - if portid == 'greenplum': - if is_rev_gte(dbver_split, get_rev_num('6.0')): + if portid == 'greenplum' or portid == 'cloudberry': + if is_rev_gte(dbver_split, get_rev_num('6.0')) or portid == 'cloudberry': ret = os.system('gpconfig -c dynamic_library_path -v \'{0}\''.format(dynamic_library_path)) else: ret = os.system('gpconfig -c dynamic_library_path -v \'\\{0}\''.format(dynamic_library_path)) @@ -1482,6 +1486,9 @@ def main(argv): else: # only need the first two digits for <= 4.3.4 dbver = '.'.join(map(str, dbver_split[:2])) + elif portid == 'cloudberry': + # Assume Apache Cloudberry will stick to semantic versioning + dbver = str(dbver_split[0]) elif portid == 'postgres': if is_rev_gte(dbver_split, get_rev_num('10.0')): # Postgres starting 10.0 uses semantic versioning. Hence, diff --git a/src/madpack/utilities.py b/src/madpack/utilities.py index 053dd112f..41b3e1e5a 100644 --- a/src/madpack/utilities.py +++ b/src/madpack/utilities.py @@ -189,6 +189,8 @@ def get_dbver(con_args, portid): # for Greenplum the 3rd digit is necessary to differentiate # 4.3.5+ from versions < 4.3.5 match = re.search("Greenplum[a-zA-Z\s]*(\d+\.\d+\.\d+)", versionStr) + elif portid == 'cloudberry': + match = re.search("Apache Cloudberry[a-zA-Z\s]*(\d+\.\d+\.\d+)", versionStr) return None if match is None else match.group(1) except Exception: error_(this, "Failed reading database version", True) diff --git a/src/ports/CMakeLists.txt b/src/ports/CMakeLists.txt index bb08e837e..0fb603390 100644 --- a/src/ports/CMakeLists.txt +++ b/src/ports/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(postgres) add_subdirectory(greenplum) +add_subdirectory(cloudberry) diff --git a/src/ports/cloudberry/2/CMakeLists.txt b/src/ports/cloudberry/2/CMakeLists.txt new file mode 100644 index 000000000..727b7714b --- /dev/null +++ b/src/ports/cloudberry/2/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +add_current_cloudberry_version() diff --git a/src/ports/cloudberry/3/CMakeLists.txt b/src/ports/cloudberry/3/CMakeLists.txt new file mode 100644 index 000000000..727b7714b --- /dev/null +++ b/src/ports/cloudberry/3/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +add_current_cloudberry_version() diff --git a/src/ports/cloudberry/CMakeLists.txt b/src/ports/cloudberry/CMakeLists.txt new file mode 100644 index 000000000..2462f3749 --- /dev/null +++ b/src/ports/cloudberry/CMakeLists.txt @@ -0,0 +1,319 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# ------------------------------------------------------------------------------ +# Cloudberry Port +# ------------------------------------------------------------------------------ + +set(PORT "Cloudberry") +string(TOUPPER ${PORT} PORT_UC) +string(TOLOWER ${PORT} PORT_LC) +set(PORT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") +get_filename_component(PORT_DIR_NAME "${PORT_SOURCE_DIR}" NAME) +set(PORT_DEPLOY_SCRIPT "${CMAKE_BINARY_DIR}/deploy/Component_${PORT}.cmake") + +if(APPLE) + # FIXME: This should be handled in a better way. + set(ADDITIONAL_GCC_FLAGS "-m64") +else(APPLE) + unset(ADDITIONAL_GCC_FLAGS) +endif(APPLE) + +list(APPEND CMAKE_MODULE_PATH + ${CMAKE_CURRENT_SOURCE_DIR}/cmake + ${CMAKE_CURRENT_SOURCE_DIR}/../postgres/cmake) +include(PostgreSQLUtils) +include(CloudberryUtils) + + +# -- 1. Specify files that will be compiled into the shared library, for *all* +# versions of this port -------------------------------------------------- + +include_directories("${CMAKE_CURRENT_SOURCE_DIR}") + +set(MAD_DBAL_SOURCES + ${MAD_SOURCES}) +list(APPEND MAD_DBAL_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/Allocator_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/Allocator_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/AnyType_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/AnyType_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/ArrayHandle_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/ArrayHandle_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/ArrayWithNullException_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/Backend.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/ByteString_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/ByteString_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/dbconnector/Compatibility.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/dbconnector.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/EigenIntegration_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/EigenIntegration_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/FunctionHandle_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/FunctionHandle_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/main.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/NewDelete.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/NativeRandomNumberGenerator_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/NativeRandomNumberGenerator_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/OutputStreamBuffer_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/OutputStreamBuffer_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/PGException_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/SystemInformation_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/SystemInformation_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/TransparentHandle_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/TransparentHandle_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/TypeTraits_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/TypeTraits_proto.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/UDF_impl.hpp" + "${CMAKE_CURRENT_SOURCE_DIR}/../postgres/dbconnector/UDF_proto.hpp" + ) + +# FIXME: Convert legacy source code written in C +# BEGIN Legacy Code + +file(GLOB_RECURSE LEGACY_C_FILES + "${CMAKE_SOURCE_DIR}/methods/*.c") +list(APPEND MAD_DBAL_SOURCES ${LEGACY_C_FILES}) + +# END Legacy Code + + +# -- 2. Copy all SQL files. Since SQL files contain file names, they are only +# preprocessed at installation time, i.e., by madpack. ------------------- + +add_sql_files( + SQL_TARGET_FILES + "../postgres/modules" + "${CMAKE_CURRENT_BINARY_DIR}/modules" +) +# Add Greenplum-specific modules. Files will be appended to SQL_TARGET_FILES. +add_sql_files( + SQL_TARGET_FILES + "modules" + "${CMAKE_CURRENT_BINARY_DIR}/modules" +) +# FIXME: Check legacy code for compliance with new architecture +# BEGIN Legacy Code + +file(GLOB_RECURSE LEGACY_SQL_FILES RELATIVE + "${CMAKE_SOURCE_DIR}/methods" + "${CMAKE_SOURCE_DIR}/methods/*.sql_in") +foreach(CURRENT_FILE ${LEGACY_SQL_FILES}) + get_filename_component(CURRENT_PATH "${CMAKE_SOURCE_DIR}/methods/${CURRENT_FILE}" ABSOLUTE) + set(OUTFILE "${CMAKE_CURRENT_BINARY_DIR}/modules/${CURRENT_FILE}") + string(REPLACE "/src/pg_gp" "" OUTFILE ${OUTFILE}) + string(REPLACE "/sql/" "/test/" OUTFILE ${OUTFILE}) + add_custom_command(OUTPUT "${OUTFILE}" + COMMAND "${CMAKE_SOURCE_DIR}/cmake/TestIfNoUTF8BOM.py" "${CURRENT_PATH}" + COMMAND ${CMAKE_COMMAND} -E copy "${CURRENT_PATH}" "${OUTFILE}" + DEPENDS "${CURRENT_PATH}" + COMMENT "Validating and copying ${CURRENT_FILE}" + ) + list(APPEND SQL_TARGET_FILES ${OUTFILE}) +endforeach(CURRENT_FILE ${LEGACY_SQL_FILES}) + +# END Legacy Code +add_custom_target(sqlFiles_${PORT_LC} ALL DEPENDS ${SQL_TARGET_FILES}) + + +# -- 3. Install all SQL files -------------------------------------------------- + +cpack_add_port_group_and_component_for_all_versions() +install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules + DESTINATION ports/${PORT_DIR_NAME} + COMPONENT ${PORT_LC}_any + REGEX "^(.*/)?\\.DS_Store\$" EXCLUDE + ) + + +# -- 4. Building the shared library is specific for each version of +# this port -------------------------------------------------------------- + +function(add_${PORT_LC}_library IN_PORT_VERSION) + add_definitions("-DIS_CLOUDBERRY") + string(REPLACE "." "_" PORT_VERSION_UNDERSCORE "${IN_PORT_VERSION}") + set(DBMS "${PORT_LC}_${PORT_VERSION_UNDERSCORE}") + set(DBMS_UC "${PORT_UC}_${PORT_VERSION_UNDERSCORE}") + + # -- 4.1. Compile C/C++ files--------------------------------------------------- + + message(">> Adding ${PORT} " + "${IN_PORT_VERSION} " + "(${${DBMS_UC}_ARCHITECTURE}) " + "to target list...") + + add_executable(${DBMS} IMPORTED) + set_target_properties(${DBMS} PROPERTIES + IMPORTED_LOCATION "${${DBMS_UC}_EXECUTABLE}" + ) + + include_directories(SYSTEM + ${${DBMS_UC}_SERVER_INCLUDE_DIR} + ${${DBMS_UC}_ADDITIONAL_INCLUDE_DIRS} + ) + + add_madlib_connector_library(madlib_${DBMS} + lib + "${${DBMS_UC}_EXECUTABLE}" + ${MAD_DBAL_SOURCES} + ) + + if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # The source code specifies that we are POSIX.1-2001 compliant: + # On the Mac, this is done in $GP_HOME/include/pg_config_manual.h. + # On Linux, gcc predefines _GNU_SOURCE, which leads to + # _POSIX_C_SOURCE being defined in /usr/include/features.h + # We therefore define HAVE_ERAND48, so that lrand48 is not redeclared + # in $GP_HOME/include/postgresql/server/port.h. + set_source_files_properties(${MAD_DBAL_SOURCES} PROPERTIES + COMPILE_FLAGS "-DHAVE_ERAND48 ${ADDITIONAL_GCC_FLAGS}") + get_property(_OLD_VALUE TARGET madlib_${DBMS} PROPERTY LINK_FLAGS) + # If property has not been initialized, _OLD_VALUE is "_OLD_VALUE-NOTFOUND" + set_target_properties(madlib_${DBMS} PROPERTIES + LINK_FLAGS "${_OLD_VALUE} ${ADDITIONAL_GCC_FLAGS}") + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") + # In syncbitvector.h, an array has zero length. This is non-standard, + # but most compilers allow it. SunPro needs an extra option. + set_source_files_properties(${MAD_DBAL_SOURCES} PROPERTIES + COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -features=zla") + endif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + + # FIXME: Convert legacy source code written in C + # BEGIN Legacy Code + + # From the CMake documentation: + # "Source file properties are visible only to targets added in the same + # directory (CMakeLists.txt)." We therefore have to set them for each + # version of this port! + if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") + # FIXME: Is there a portable (not just for gcc) way of including a header file? + # Due to Greenplum bug MPP-13254, we need to include + # before + # FIXME: In the C code, we have several places where strict aliasing + # rules are violated. See this web page for some background: + # http://dbp-consulting.com/tutorials/StrictAliasing.html + # For now, we tell GCC that it cannot rely on strict aliasing rules. + # Downside: We forgo some potential optimization. + # The warning GCC would output without -fno-strict-aliasing is: + # dereferencing type-punned pointer will break strict-aliasing rules + set_source_files_properties(${LEGACY_C_FILES} PROPERTIES + COMPILE_FLAGS "-fno-strict-aliasing -include sys/time.h ${ADDITIONAL_GCC_FLAGS}") + endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang") + + set_source_files_properties(${LEGACY_C_FILES} PROPERTIES + COMPILE_DEFINITIONS "NO_PG_MODULE_MAGIC" + ) + + # sparse_vector.c indirectly includes openssl/ssl.h (via libpq/libpq-be.h) + # removed due to we take out libpq/libpq-be.h + # include_directories(SYSTEM ${${DBMS_UC}_CLIENT_INCLUDE_DIR}) + + # END Legacy Code + + + # -- 4.2. Preprocess all Python files ------------------------------------------ + + define_cloudberry_features(${IN_PORT_VERSION} DBMS_FEATURES) + define_m4_macros(M4_DEFINES_CMD_LINE M4_DEFINES_CODE ${DBMS_FEATURES}) + + add_python_files( + PYTHON_TARGET_FILES + "${PORT_SOURCE_DIR}/../postgres/modules" + "${CMAKE_CURRENT_BINARY_DIR}/modules" + ${M4_DEFINES_CMD_LINE} + ) + # FIXME: Check legacy code for compliance with new architecture + # BEGIN Legacy Code + + file(GLOB_RECURSE LEGACY_PYTHON_FILES RELATIVE + "${CMAKE_SOURCE_DIR}/methods" + "${CMAKE_SOURCE_DIR}/methods/*.py_in") + foreach(CURRENT_FILE ${LEGACY_PYTHON_FILES}) + get_filename_component(CURRENT_PATH "${CMAKE_SOURCE_DIR}/methods/${CURRENT_FILE}" ABSOLUTE) + set(OUTFILE "${CMAKE_CURRENT_BINARY_DIR}/modules/${CURRENT_FILE}") + string(REPLACE "/src/pg_gp" "" OUTFILE ${OUTFILE}) + string(REGEX REPLACE ".py_in\$" ".py" OUTFILE ${OUTFILE}) + get_dir_name(OUTDIR ${OUTFILE}) + add_custom_command(OUTPUT "${OUTFILE}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${OUTDIR}" + COMMAND ${M4_BINARY} ${M4_ARGUMENTS} ${M4_DEFINES_CMD_LINE} + "${CURRENT_PATH}" > "${OUTFILE}" + DEPENDS "${CURRENT_PATH}" + COMMENT "Preprocessing ${CURRENT_FILE} with m4." + ) + list(APPEND PYTHON_TARGET_FILES ${OUTFILE}) + endforeach(CURRENT_FILE ${LEGACY_PYTHON_FILES}) + + # END Legacy Code + + configure_file("${PORT_SOURCE_DIR}/../postgres/madpack/SQLCommon.m4_in" + "${CMAKE_CURRENT_BINARY_DIR}/madpack/SQLCommon.m4" + @ONLY + ) + + add_custom_target(pythonFiles_${DBMS} ALL + DEPENDS ${PYTHON_TARGET_FILES}) + + + # -- 4.3. Install shared library, Python files, and M4 header ------------------ + + cpack_add_version_component() + install(TARGETS madlib_${DBMS} + LIBRARY DESTINATION ports/${PORT_DIR_NAME}/${IN_PORT_VERSION}/lib + COMPONENT ${DBMS} + ) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/modules + DESTINATION ports/${PORT_DIR_NAME}/${IN_PORT_VERSION} + COMPONENT ${DBMS} + REGEX "^(.*/)?\\.DS_Store\$" EXCLUDE + ) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/madpack/SQLCommon.m4" + DESTINATION ports/${PORT_DIR_NAME}/${IN_PORT_VERSION}/madpack + COMPONENT ${DBMS} + ) + + # -- 4.4. Generate gppkg deployment scripts. Note: These are generated CMake + # scripts! --------------------------------------------------------------- + add_gppkg(${IN_PORT_VERSION} Cloudberry cbdb 1.0) + +endfunction(add_${PORT_LC}_library) + + +# -- 5. Provide a macro to be called from CMakeLists.txt in the version +# directory. We want these files to be one-liners. ----------------------- + +# Add the current version as a target. This is a macro because it calls +# find_package, and we want the side effects (the defined variables) to be +# visible after the invocation +macro(add_current_${PORT_LC}_version) + get_filename_component(_VERSION "${CMAKE_CURRENT_SOURCE_DIR}" NAME) + string(REPLACE "." "_" _VERSION_UNDERSCORES ${_VERSION}) + + find_package(${PORT}_${_VERSION_UNDERSCORES}) + if(${PORT_UC}_${_VERSION_UNDERSCORES}_FOUND) + add_cloudberry_library(${_VERSION}) + endif(${PORT_UC}_${_VERSION_UNDERSCORES}_FOUND) +endmacro(add_current_${PORT_LC}_version) + + +# -- 6. Build shared library and copy version-specific file for all +# ${PORT_UC}_X_Y_PG_CONFIG macros defined by the user. If none has been +# defined, try to find any version this port. ---------------------------- + +determine_target_versions(VERSIONS) +foreach(VERSION ${VERSIONS}) + add_subdirectory(${VERSION}) +endforeach(VERSION) diff --git a/src/ports/cloudberry/cmake/CloudberryUtils.cmake b/src/ports/cloudberry/cmake/CloudberryUtils.cmake new file mode 100644 index 000000000..2d1e26f68 --- /dev/null +++ b/src/ports/cloudberry/cmake/CloudberryUtils.cmake @@ -0,0 +1,96 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Define Cloudberry feature macros +# +function(define_cloudberry_features IN_VERSION OUT_FEATURES) + list(APPEND ${OUT_FEATURES} __HAS_ORDERED_AGGREGATES__) + list(APPEND ${OUT_FEATURES} __HAS_FUNCTION_PROPERTIES__) + list(APPEND ${OUT_FEATURES} __HAS_BOOL_TO_TEXT_CAST__) + + # Pass values to caller + set(${OUT_FEATURES} "${${OUT_FEATURES}}" PARENT_SCOPE) +endfunction(define_cloudberry_features) + +function(add_gppkg GPDB_VERSION GPDB_VARIANT GPDB_VARIANT_SHORT UPGRADE_SUPPORT) + string(TOLOWER ${GPDB_VERSION} GPDB_VERSION_LC) + string(REPLACE "." "_" VERSION_ "${GPDB_VERSION}") + + # Get information about the rhel version + rh_version(RH_VERSION) + string(REGEX MATCH "([0-9])" RH_MAJOR_VERSION "${RH_VERSION}") + + if("${OSVER}" STREQUAL "kylin") + string(REGEX MATCH "([0-9]+)" RH_MAJOR_VERSION "${RH_VERSION}") + endif("${OSVER}" STREQUAL "kylin") + + string(CONCAT OS ${OSVER} ${RH_MAJOR_VERSION}) + + file(WRITE "${CMAKE_BINARY_DIR}/deploy/gppkg/${GPDB_VARIANT}_${VERSION_}_gppkg.cmake" " + file(MAKE_DIRECTORY + \"\${CMAKE_CURRENT_BINARY_DIR}/${GPDB_VERSION}/BUILD\" + \"\${CMAKE_CURRENT_BINARY_DIR}/${GPDB_VERSION}/SPECS\" + \"\${CMAKE_CURRENT_BINARY_DIR}/${GPDB_VERSION}/RPMS\" + \"\${CMAKE_CURRENT_BINARY_DIR}/${GPDB_VERSION}/gppkg\" + ) + + set(GPDB_VERSION \"${GPDB_VERSION}\") + set(GPDB_VERSION_LC \"${GPDB_VERSION_LC}\") + set(GPDB_VARIANT \"${GPDB_VARIANT}\") + set(GPDB_VARIANT_SHORT \"${GPDB_VARIANT_SHORT}\") + set(UPGRADE_SUPPORT \"${UPGRADE_SUPPORT}\") + set(OS \"${OS}\") + set(RH_MAJOR_VERSION \"${RH_MAJOR_VERSION}\") + string(TOLOWER \"${GPDB_VARIANT}\" PORT_NAME) + + configure_file( + madlib.spec.in + \"\${CMAKE_CURRENT_BINARY_DIR}/${GPDB_VERSION}/SPECS/madlib.spec\" + ) + configure_file( + gppkg_spec.yml.in + \"\${CMAKE_CURRENT_BINARY_DIR}/${GPDB_VERSION}/gppkg/gppkg_spec.yml\" + ) + + if(GPPKG_BINARY AND RPMBUILD_BINARY) + add_custom_target(gppkg_${GPDB_VARIANT}_${VERSION_} + COMMAND cmake -E create_symlink \"\${MADLIB_GPPKG_RPM_SOURCE_DIR}\" + \"\${CPACK_PACKAGE_FILE_NAME}-gppkg\" + COMMAND \"\${RPMBUILD_BINARY}\" -bb SPECS/madlib.spec + COMMAND cmake -E rename \"RPMS/\${MADLIB_GPPKG_RPM_FILE_NAME}\" + \"gppkg/\${MADLIB_GPPKG_RPM_FILE_NAME}\" + COMMAND \"\${GPPKG_BINARY}\" --build gppkg + DEPENDS \"${CMAKE_BINARY_DIR}/\${CPACK_PACKAGE_FILE_NAME}.rpm\" + WORKING_DIRECTORY \"\${CMAKE_CURRENT_BINARY_DIR}/${GPDB_VERSION}\" + COMMENT \"Generating ${GPDB_VARIANT} ${GPDB_VERSION} gppkg installer...\" + VERBATIM + ) + else(GPPKG_BINARY AND RPMBUILD_BINARY) + add_custom_target(gppkg_${GPDB_VARIANT}_${VERSION_} + COMMAND cmake -E echo \"Could not find gppkg and/or rpmbuild.\" + \"Please rerun cmake.\" + ) + endif(GPPKG_BINARY AND RPMBUILD_BINARY) + + # Unfortunately, we cannot set a dependency to the built-in package target, + # i.e., the following does not work: + # add_dependencies(gppkg package) + + add_dependencies(gppkg gppkg_${GPDB_VARIANT}_${VERSION_}) + ") +endfunction(add_gppkg) + diff --git a/src/ports/cloudberry/cmake/FindCloudberry.cmake b/src/ports/cloudberry/cmake/FindCloudberry.cmake new file mode 100644 index 000000000..fa7b13d99 --- /dev/null +++ b/src/ports/cloudberry/cmake/FindCloudberry.cmake @@ -0,0 +1,46 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# Set defaults that can be overridden by files that include this file: +if(NOT DEFINED _FIND_PACKAGE_FILE) + set(_FIND_PACKAGE_FILE "${CMAKE_CURRENT_LIST_FILE}") +endif(NOT DEFINED _FIND_PACKAGE_FILE) + +# Set parameters for calling FindPostgreSQL.cmake +set(_NEEDED_PG_CONFIG_PACKAGE_NAME "Apache Cloudberry") +set(_PG_CONFIG_VERSION_NUM_MACRO "GP_VERSION_NUM") +set(_PG_CONFIG_VERSION_MACRO "GP_VERSION") +set(_SEARCH_PATH_HINTS + "/usr/local/cloudberry-db-devel/bin" + "/usr/local/cloudberry-db/bin" + "/usr/local/cloudberry/bin" + "$ENV{GPHOME}/bin" +) + +include("${CMAKE_CURRENT_LIST_DIR}/../../postgres/cmake/FindPostgreSQL.cmake") + +if(${PKG_NAME}_FOUND) + # server/funcapi.h ultimately includes server/access/xact.h, from which + # cdb/cdbpathlocus.h is included + execute_process(COMMAND ${${PKG_NAME}_PG_CONFIG} --pkgincludedir + OUTPUT_VARIABLE ${PKG_NAME}_ADDITIONAL_INCLUDE_DIRS + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(${PKG_NAME}_ADDITIONAL_INCLUDE_DIRS + "${${PKG_NAME}_ADDITIONAL_INCLUDE_DIRS}/internal") + message("-- Detected Apache Cloudberry") +endif(${PKG_NAME}_FOUND) diff --git a/src/ports/cloudberry/cmake/FindCloudberry_2.cmake b/src/ports/cloudberry/cmake/FindCloudberry_2.cmake new file mode 120000 index 000000000..487a586bc --- /dev/null +++ b/src/ports/cloudberry/cmake/FindCloudberry_2.cmake @@ -0,0 +1 @@ +FindCloudberry.cmake \ No newline at end of file diff --git a/src/ports/cloudberry/cmake/FindCloudberry_3.cmake b/src/ports/cloudberry/cmake/FindCloudberry_3.cmake new file mode 120000 index 000000000..487a586bc --- /dev/null +++ b/src/ports/cloudberry/cmake/FindCloudberry_3.cmake @@ -0,0 +1 @@ +FindCloudberry.cmake \ No newline at end of file diff --git a/src/ports/cloudberry/dbconnector/Compatibility.hpp b/src/ports/cloudberry/dbconnector/Compatibility.hpp new file mode 100644 index 000000000..f718b5299 --- /dev/null +++ b/src/ports/cloudberry/dbconnector/Compatibility.hpp @@ -0,0 +1,86 @@ +/* ----------------------------------------------------------------------- *//** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * @file cloudberry/dbconnector/Compatibility.cpp + * + *//* ----------------------------------------------------------------------- */ + +#ifndef MADLIB_CLOUDBERRY_COMPATIBILITY_HPP +#define MADLIB_CLOUDBERRY_COMPATIBILITY_HPP + +namespace madlib { + +namespace dbconnector { + +namespace postgres { + +namespace { +// No need to make these function accessible outside of the postgres namespace. + +#ifndef PG_GET_COLLATION +// Greenplum does not currently have support for collations +#define PG_GET_COLLATION() InvalidOid +#endif + +#ifndef SearchSysCache1 +// See madlib_SearchSysCache1() +#define SearchSysCache1(cacheId, key1) \ + SearchSysCache(cacheId, key1, 0, 0, 0) +#endif + +} // namespace + +inline ArrayType* madlib_construct_array + ( + Datum* elems, + int nelems, + Oid elmtype, + int elmlen, + bool elmbyval, + char elmalign + ){ + return + construct_array( + elems, nelems, elmtype, elmlen, elmbyval, elmalign); +} + +inline ArrayType* madlib_construct_md_array + ( + Datum* elems, + bool* nulls, + int ndims, + int* dims, + int* lbs, + Oid elmtype, + int elmlen, + bool elmbyval, + char elmalign + ){ + return + construct_md_array( + elems, nulls, ndims, dims, lbs, elmtype, elmlen, elmbyval, + elmalign); +} + +} // namespace postgres + +} // namespace dbconnector + +} // namespace madlib + +#endif // defined(MADLIB_CLOUDBERRY_COMPATIBILITY_HPP) diff --git a/src/ports/cloudberry/dbconnector/dbconnector.hpp b/src/ports/cloudberry/dbconnector/dbconnector.hpp new file mode 100644 index 000000000..c875ced5a --- /dev/null +++ b/src/ports/cloudberry/dbconnector/dbconnector.hpp @@ -0,0 +1,67 @@ +/* ----------------------------------------------------------------------- *//** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * @file dbconnector.hpp + * + * @brief This file should be included by user code (and nothing else) + * + *//* ----------------------------------------------------------------------- */ + +#ifndef MADLIB_CLOUDBERRY_DBCONNECTOR_HPP +#define MADLIB_CLOUDBERRY_DBCONNECTOR_HPP + +// On platforms based on PostgreSQL we can include a different set of headers. +#define MADLIB_POSTGRES_HEADERS + +extern "C" { +#include +#include +#include +#include +#include // Greenplum requires this for GetAttributeByNum() +#include // Memory allocation, e.g., HOLD_INTERRUPTS +#include +#include +#include // needed for string_to_text()、cstring_to_text_with_len() +#include // needed for errstart_cold +#include // needed for format_procedure() +#include // needed for oid_hash +#include +#include // for type lookup, e.g., type_is_rowtype +#include +#include // for direct access to catalog, e.g., SearchSysCache() +#include // type conversion, e.g., lookup_rowtype_tupdesc +#include "../../../../methods/svec/src/pg_gp/sparse_vector.h" // Legacy sparse vectors +} // extern "C" + +Datum drandom(PG_FUNCTION_ARGS); +Datum setseed(PG_FUNCTION_ARGS); + +#ifdef sprintf +#undef sprintf +#endif + +#ifdef snprintf +#undef snprintf +#endif + +#include "Compatibility.hpp" + +#include "../../postgres/dbconnector/dbconnector.hpp" + +#endif // defined(MADLIB_CLOUDBERRY_DBCONNECTOR_HPP) diff --git a/src/ports/postgres/cmake/PostgreSQLUtils.cmake b/src/ports/postgres/cmake/PostgreSQLUtils.cmake index 6f16d79a1..02d4e502a 100644 --- a/src/ports/postgres/cmake/PostgreSQLUtils.cmake +++ b/src/ports/postgres/cmake/PostgreSQLUtils.cmake @@ -87,6 +87,9 @@ function(determine_target_versions OUT_VERSIONS) # Starting Postgresql 10, semantic versioning will be followed, # implying we only need 1 folder for same major versions set(VERSION ${${PORT_UC}_VERSION_MAJOR}) + elseif(${PORT_UC} STREQUAL "CLOUDBERRY") + # Assumes Apache Cloudberry always follows semantic versioning + set(VERSION ${${PORT_UC}_VERSION_MAJOR}) endif() list(FIND SUPPORTED_VERSIONS "${VERSION}" _POS) diff --git a/src/ports/postgres/dbconnector/Allocator_impl.hpp b/src/ports/postgres/dbconnector/Allocator_impl.hpp index 4c442070e..ee7c9838b 100644 --- a/src/ports/postgres/dbconnector/Allocator_impl.hpp +++ b/src/ports/postgres/dbconnector/Allocator_impl.hpp @@ -172,6 +172,7 @@ Allocator::reallocate(void *inPtr, const size_t inSize) const { * * @see See also the notes for PGAllocator::allocate(const size_t) and * PGAllocator::allocate(const size_t, const std::nothrow_t&) + * CBDB_FIX: see Allocator::makeAligned */ template inline @@ -186,7 +187,8 @@ Allocator::free(void *inPtr) const { */ HOLD_INTERRUPTS(); PG_TRY(); { - pfree(unaligned(inPtr)); + void* ptr = unaligned(inPtr); + ptr ? pfree(ptr) : std::free(inPtr); } PG_CATCH(); { FlushErrorState(); } PG_END_TRY(); @@ -214,11 +216,11 @@ Allocator::internalPalloc(size_t inSize) const { #if MAXIMUM_ALIGNOF >= 16 return (ZM == dbal::DoZero) ? palloc0(inSize) : palloc(inSize); #else - if (inSize > std::numeric_limits::max() - 16) + if (inSize > std::numeric_limits::max() - 32) return NULL; /* Precondition: inSize <= std::numeric_limits::max() - 16 */ - const size_t size = inSize + 16; + const size_t size = inSize + 32; void *raw = (ZM == dbal::DoZero) ? palloc0(size) : palloc(size); return makeAligned(raw); #endif @@ -246,14 +248,18 @@ Allocator::internalRePalloc(void *inPtr, size_t inSize) const { #if MAXIMUM_ALIGNOF >= 16 return repalloc(inPtr, inSize); #else - if (inSize > std::numeric_limits::max() - 16) { - pfree(unaligned(inPtr)); + void* ptr = unaligned(inPtr); + if (!ptr) + return std::realloc(inPtr, inSize); + + if (inSize > std::numeric_limits::max() - 32) { + pfree(ptr); return NULL; } /* Precondition: inSize <= std::numeric_limits::max() - 16 */ - const size_t size = inSize + 16; - void *raw = repalloc(unaligned(inPtr), size); + const size_t size = inSize + 32; + void *raw = repalloc(ptr, size); if (ZM == dbal::DoZero) { std::fill( @@ -269,6 +275,9 @@ Allocator::internalRePalloc(void *inPtr, size_t inSize) const { * @internal * @brief Return next 16-byte boundary after inPtr and store inPtr in word * immediately before that + * CBDB_FIX: A weird bug causes std::malloc to be called for allocation, + * but custom free for destruction. Hacky workacound this by prepending + * each chunk with a magic number 0xCBDBCBDB to indicate custom allocation. */ inline void * @@ -282,8 +291,9 @@ Allocator::makeAligned(void *inPtr) const { * to us an can be written to safely. */ void *aligned = reinterpret_cast( - (reinterpret_cast(inPtr) & ~(uintptr_t(15))) + 16); + (reinterpret_cast(inPtr) & ~(uintptr_t(15))) + 32); *(reinterpret_cast(aligned) - 1) = inPtr; + *(reinterpret_cast(aligned) - 2) = 0xCBDBCBDB; return aligned; } @@ -291,6 +301,7 @@ Allocator::makeAligned(void *inPtr) const { * @internal * @brief Return the address of memory block that corresponds to the given * 16-byte aligned address + * @see CBDB_FIX: see Allocator::makeAligned * * Unless MAXIMUM_ALIGNOF >= 16, we free the block of memory pointed to * by the word immediately in front of the memory pointed to by \c inPtr. @@ -301,6 +312,11 @@ Allocator::unaligned(void *inPtr) const { #if MAXIMUM_ALIGNOF >= 16 return inPtr; #else + size_t magic = *(reinterpret_cast(inPtr) - 2); + if (magic != 0xCBDBCBDB) { + elog(WARNING, "non-custom-allocator allocation detected"); + return nullptr; + } return (*(reinterpret_cast(inPtr) - 1)); #endif } diff --git a/src/ports/postgres/dbconnector/NewDelete.cpp b/src/ports/postgres/dbconnector/NewDelete.cpp index f030f07a2..f9ecb5fdb 100644 --- a/src/ports/postgres/dbconnector/NewDelete.cpp +++ b/src/ports/postgres/dbconnector/NewDelete.cpp @@ -25,6 +25,7 @@ // We do not write #include "dbconnector.hpp" here because we want to rely on // the search paths, which might point to a port-specific dbconnector.hpp #include +#include #if _GLIBCXX_USE_CXX11_ABI #define THROW_BAD_ALLOC @@ -113,3 +114,17 @@ void operator delete[](void *ptr, const std::nothrow_t&) NOEXCEPT { madlib::defaultAllocator().free(ptr); } + +#ifdef __cpp_sized_deallocation +void +operator delete(void *ptr, std::size_t sz) NOEXCEPT { + (void)sz; + madlib::defaultAllocator().free(ptr); +} + +void +operator delete[](void *ptr, std::size_t sz) NOEXCEPT { + (void)sz; + madlib::defaultAllocator().free(ptr); +} +#endif diff --git a/src/ports/postgres/dbconnector/SystemInformation_impl.hpp b/src/ports/postgres/dbconnector/SystemInformation_impl.hpp index 313906b40..a7ada5e34 100644 --- a/src/ports/postgres/dbconnector/SystemInformation_impl.hpp +++ b/src/ports/postgres/dbconnector/SystemInformation_impl.hpp @@ -4,7 +4,7 @@ * *//* ----------------------------------------------------------------------- */ -#if GP_VERSION_NUM >= 70000 || PG_VERSION_NUM >= 130000 +#if defined(IS_CLOUDBERRY) || GP_VERSION_NUM >= 70000 || PG_VERSION_NUM >= 130000 extern "C"{ #include extern uint32 uint32_hash(const void *key, Size keysize); @@ -34,7 +34,7 @@ initializeOidHashTable(HTAB*& ioHashTable, MemoryContext inCacheContext, HASHCTL ctl; ctl.keysize = sizeof(Oid); ctl.entrysize = inEntrySize; -#if GP_VERSION_NUM >= 70000 || PG_VERSION_NUM >= 130000 +#if defined(IS_CLOUDBERRY) || GP_VERSION_NUM >= 70000 || PG_VERSION_NUM >= 130000 ctl.hash = uint32_hash; #else ctl.hash = oid_hash; diff --git a/src/ports/postgres/modules/pmml/table_to_pmml.sql_in b/src/ports/postgres/modules/pmml/table_to_pmml.sql_in index 09b078c60..ac5d01aeb 100644 --- a/src/ports/postgres/modules/pmml/table_to_pmml.sql_in +++ b/src/ports/postgres/modules/pmml/table_to_pmml.sql_in @@ -307,6 +307,14 @@ File table_to_pmml.sql_in documenting the PMML export functions. CREATE OR REPLACE FUNCTION MADLIB_SCHEMA.pmml( model_table varchar ) RETURNS xml AS $$ + +import collections +import collections.abc +if not hasattr(collections, 'MutableSequence'): + collections.MutableSequence = collections.abc.MutableSequence + collections.MutableMapping = collections.abc.MutableMapping + collections.MutableSet = collections.abc.MutableSet + PythonFunction(pmml, table_to_pmml, table_to_pmml) $$ LANGUAGE plpython3u m4_ifdef(`__HAS_FUNCTION_PROPERTIES__', `READS SQL DATA', `'); @@ -325,6 +333,14 @@ CREATE OR REPLACE FUNCTION MADLIB_SCHEMA.pmml( model_table varchar , name_spec varchar ) RETURNS xml AS $$ + +import collections +import collections.abc +if not hasattr(collections, 'MutableSequence'): + collections.MutableSequence = collections.abc.MutableSequence + collections.MutableMapping = collections.abc.MutableMapping + collections.MutableSet = collections.abc.MutableSet + PythonFunction(pmml, table_to_pmml, table_to_pmml) $$ LANGUAGE plpython3u m4_ifdef(`__HAS_FUNCTION_PROPERTIES__', `READS SQL DATA', `'); @@ -343,6 +359,14 @@ CREATE OR REPLACE FUNCTION MADLIB_SCHEMA.pmml( model_table varchar , name_spec varchar[] ) RETURNS xml AS $$ + +import collections +import collections.abc +if not hasattr(collections, 'MutableSequence'): + collections.MutableSequence = collections.abc.MutableSequence + collections.MutableMapping = collections.abc.MutableMapping + collections.MutableSet = collections.abc.MutableSet + PythonFunction(pmml, table_to_pmml, table_to_pmml) $$ LANGUAGE plpython3u m4_ifdef(`__HAS_FUNCTION_PROPERTIES__', `READS SQL DATA', `'); @@ -351,6 +375,14 @@ m4_ifdef(`__HAS_FUNCTION_PROPERTIES__', `READS SQL DATA', `'); -- Help messages ------------------------------------------------------- CREATE OR REPLACE FUNCTION MADLIB_SCHEMA.pmml() RETURNS TEXT AS $$ + +import collections +import collections.abc +if not hasattr(collections, 'MutableSequence'): + collections.MutableSequence = collections.abc.MutableSequence + collections.MutableMapping = collections.abc.MutableMapping + collections.MutableSet = collections.abc.MutableSet + PythonFunction(pmml, table_to_pmml, pmml_help_msg) $$ LANGUAGE plpython3u IMMUTABLE m4_ifdef(`__HAS_FUNCTION_PROPERTIES__', `CONTAINS SQL', `');