Skip to content

GH-47876: [C++][FlightRPC] ODBC: macOS .PKG installer for Intel and ARM#49766

Open
alinaliBQ wants to merge 3 commits intoapache:mainfrom
Bit-Quill:gh-47876-mac-pkg
Open

GH-47876: [C++][FlightRPC] ODBC: macOS .PKG installer for Intel and ARM#49766
alinaliBQ wants to merge 3 commits intoapache:mainfrom
Bit-Quill:gh-47876-mac-pkg

Conversation

@alinaliBQ
Copy link
Copy Markdown
Collaborator

@alinaliBQ alinaliBQ commented Apr 15, 2026

Rationale for this change

Generate and upload macOS .pkg installer in CI. The installer is unsigned.

What changes are included in this PR?

Adds in support for macOS .PKG Installer for Intel and ARM. It will install:

/Library/ODBC/arrow-odbc
├── doc
│   ├── Connection-Options.md
│   └── LICENSE.txt
└── lib
    ├── libarrow_flight_sql_odbc.2400.0.0.dylib
    ├── libarrow_flight_sql_odbc.2400.dylib -> libarrow_flight_sql_odbc.2400.0.0.dylib
    └── libarrow_flight_sql_odbc.dylib -> libarrow_flight_sql_odbc.2400.dylib

3 directories, 5 files

If Apache Arrow Flight SQL ODBC is already registered in the system DSN on the user machine, the installer will not overwrite the registration.

Are these changes tested?

Tested on Intel macOS. Team will test ARM installer using ARM machine later.

Are there any user-facing changes?

Developers can download the .pkg installers for usage.

@github-actions github-actions Bot added the awaiting review Awaiting review label Apr 15, 2026
@github-actions
Copy link
Copy Markdown

⚠️ GitHub issue #47876 has been automatically assigned in GitHub to PR creator.

Co-authored-by: vic-tsang <victor.tsang@improving.com>

cpp/src/arrow/flight/sql/odbc/install/unix/install_odbc_ini.sh is originally authored by  vic-tsang <victor.tsang@improving.com>

---------------------------------------

* Initial draft for macOS .pkg installer

* in-progress for `install_odbc`

* Remove `$HOME` from registration script

* Generate .pkg installer and attempts to fix installer

* Attempt to fix doc not seen
* Attempt to fix ODBC registration script

* Fix installer script and doc

* Rename `install_odbc_ini.sh` to `postinstall`

* Reuse `install_odbc.sh` script inside `postinstall`

* Fix to generate macOS installer

- Check $(pwd)/build/cpp

* Clean up PR and todos

* Update format to re-use code

* Use `install_odbc_ini.sh` script to install DSN

Keep a lightweight `postinstall` file for macOS

* Update install_odbc_ini.sh execution access

* Address Justin's comment
@alinaliBQ alinaliBQ marked this pull request as ready for review April 16, 2026 17:55
@alinaliBQ
Copy link
Copy Markdown
Collaborator Author

@lidavidm @kou PR is ready for review, please have a look

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds macOS .pkg packaging support for the Arrow Flight SQL ODBC driver, integrating installer generation into CI and providing post-install registration scripts/resources.

Changes:

  • Add macOS CPack productbuild configuration for an ODBC .pkg installer (including postinstall registration and bundled docs).
  • Introduce a Unix DSN registration helper (install_odbc_ini.sh) and a macOS postinstall script to register the driver + DSN.
  • Update CI and repo configs to build/upload the .pkg and accommodate new installer resource files.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
dev/release/rat_exclude_files.txt Excludes new macOS installer resource text files from RAT scanning.
cpp/src/arrow/flight/sql/odbc/install/unix/install_odbc_ini.sh Adds a DSN registration script for system odbc.ini.
cpp/src/arrow/flight/sql/odbc/install/unix/install_odbc.sh Adjusts macOS driver registration to write to system /Library/ODBC/odbcinst.ini.
cpp/src/arrow/flight/sql/odbc/install/mac/postinstall Adds post-install script to register driver + DSN and delete temporary scripts.
cpp/src/arrow/flight/sql/odbc/install/mac/Welcome.txt Adds installer welcome text resource.
cpp/src/arrow/flight/sql/odbc/install/mac/README.txt Adds installer readme text resource with setup steps.
cpp/src/arrow/flight/sql/odbc/Connection-Options.md Adds a (currently placeholder) connection options doc intended to be shipped in the installer.
cpp/src/arrow/flight/sql/odbc/CMakeLists.txt Adds macOS CPack config, installs driver/scripts/docs, and defines Docs component for UNIX.
.pre-commit-config.yaml Adds new scripts to ShellCheck scope.
.github/workflows/cpp_extra.yml Enables ODBC installer build, runs cpack, and uploads .pkg artifacts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +168 to +179
set(CPACK_SET_DESTDIR ON)
set(CPACK_INSTALL_PREFIX "/Library/ODBC")
# Register ODBC after install
set(CPACK_POSTFLIGHT_ARROW_FLIGHT_SQL_ODBC_SCRIPT
"${CMAKE_CURRENT_SOURCE_DIR}/install/mac/postinstall")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/install/mac/README.txt")
set(CPACK_RESOURCE_FILE_WELCOME
"${CMAKE_CURRENT_SOURCE_DIR}/install/mac/Welcome.txt")

set(ODBC_INSTALL_DIR "arrow-odbc/lib")
set(DOC_INSTALL_DIR "arrow-odbc/doc")
else()
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The linked issue description calls out installing the driver under /Library/Apache/ArrowFlightSQLODBC/lib/..., but this packaging installs under /Library/ODBC/arrow-odbc/... (via CPACK_INSTALL_PREFIX and ODBC_INSTALL_DIR). Please confirm the intended install root and align with the issue (or update the issue/PR description) to avoid shipping an installer that doesn't meet the documented path expectation.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/Library/ODBC/arrow-odbc/ is the correct destination.

Comment on lines +218 to +220
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/Connection-Options.md"
DESTINATION "${DOC_INSTALL_DIR}"
COMPONENT Docs)
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Connection-Options.md is installed into the package (Docs component) but currently only contains a TODO placeholder. Since this is user-facing documentation shipped with the installer, it should either be populated with the supported keys/options or omitted from installation until it has real content.

Suggested change
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/Connection-Options.md"
DESTINATION "${DOC_INSTALL_DIR}"
COMPONENT Docs)

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TODO will be addressed before this is shipped.

Comment on lines +3 to +9
To setup a connection, you can use DSN to store your data source connection information.
1. Open 'iODBC Data Source Administrator'.
2. To create a user DSN, go to 'User DSN' tab and click 'Add'.
3. Select 'Apache Arrow Flight SQL ODBC Driver' and click 'Finish'.
4. Enter DSN name and connection string values.
For the list of all supported options, check '/Library/ODBC/arrow-odbc/doc/Connection-Options.md'.
5. Click 'Ok' to save the DSN.
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User-facing text fixes: change "To setup a connection" to "To set up a connection" (grammar), change "Ok" to "OK", and remove the trailing whitespace at the end of line 7. Since this README is used as an installer resource, it should be polished.

Suggested change
To setup a connection, you can use DSN to store your data source connection information.
1. Open 'iODBC Data Source Administrator'.
2. To create a user DSN, go to 'User DSN' tab and click 'Add'.
3. Select 'Apache Arrow Flight SQL ODBC Driver' and click 'Finish'.
4. Enter DSN name and connection string values.
For the list of all supported options, check '/Library/ODBC/arrow-odbc/doc/Connection-Options.md'.
5. Click 'Ok' to save the DSN.
To set up a connection, you can use DSN to store your data source connection information.
1. Open 'iODBC Data Source Administrator'.
2. To create a user DSN, go to 'User DSN' tab and click 'Add'.
3. Select 'Apache Arrow Flight SQL ODBC Driver' and click 'Finish'.
4. Enter DSN name and connection string values.
For the list of all supported options, check '/Library/ODBC/arrow-odbc/doc/Connection-Options.md'.
5. Click 'OK' to save the DSN.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 48 to +50
# macOS
USER_ODBCINST_FILE="$HOME/Library/ODBC/odbcinst.ini"
mkdir -p "$HOME"/Library/ODBC
USER_ODBCINST_FILE="/Library/ODBC/odbcinst.ini"
mkdir -p /Library/ODBC
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On macOS this script now writes to the system-level /Library/ODBC/odbcinst.ini, but the variable is still named USER_ODBCINST_FILE. Renaming it to reflect that it's a system-wide file would reduce confusion for future maintenance (especially since the script requires sudo).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to ODBCINST_FILE.

Comment on lines +20 to +30
# Use temporary driver registration script to register ODBC driver in system DSN
odbc_install_script="/Library/ODBC/arrow-odbc/lib/install_odbc.sh"
"$odbc_install_script" /Library/ODBC/arrow-odbc/lib/libarrow_flight_sql_odbc.dylib

# Use temporary DSN registration script to register sample system DSN
dsn_install_script="/Library/ODBC/arrow-odbc/lib/install_odbc_ini.sh"
"$dsn_install_script" /Library/ODBC/odbc.ini

# clean temporary script
rm -f "$odbc_install_script"
rm -f "$dsn_install_script"
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The postinstall script doesn't enable strict error handling (e.g., set -euo pipefail). As written, if either registration script fails, the postinstall can still exit successfully because the final rm -f commands will return 0, leaving the driver/DSN unregistered while the installer reports success. Please fail fast on any error and consider emitting a clear error message if registration fails.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines +20 to +31
SYSTEM_ODBC_FILE="$1"

if [[ -z "$SYSTEM_ODBC_FILE" ]]; then
echo "error: path to system ODBC DSN is not specified. Call format: install_odbc_ini abs_path_to_odbc_dsn_ini"
exit 1
fi

DRIVER_NAME="Apache Arrow Flight SQL ODBC Driver"
DSN_NAME="Apache Arrow Flight SQL ODBC DSN"

touch "$SYSTEM_ODBC_FILE"

Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script doesn't use strict mode (set -euo pipefail) like install_odbc.sh does. Without it, failures from commands like touch, awk, or mv may go unnoticed depending on where they occur, which is risky for an installer-time system configuration update. Please add strict mode and ensure any failures propagate as a non-zero exit code.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines +48 to +64
# Check if [ODBC Data Sources] section exists
if grep -q '^\[ODBC Data Sources\]' "$SYSTEM_ODBC_FILE"; then
# Section exists: check if DSN entry exists
if ! grep -q "^${DSN_NAME}=" "$SYSTEM_ODBC_FILE"; then
# Add DSN entry under [ODBC Data Sources] section

# Use awk to insert the line immediately after [ODBC Data Sources]
awk -v dsn="$DSN_NAME" -v driver="$DRIVER_NAME" '
$0 ~ /^\[ODBC Data Sources\]/ && !inserted {
print
print dsn "=" driver
inserted=1
next
}
{ print }
' "$SYSTEM_ODBC_FILE" > "${SYSTEM_ODBC_FILE}.tmp" && mv "${SYSTEM_ODBC_FILE}.tmp" "$SYSTEM_ODBC_FILE"
fi
Copy link

Copilot AI Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The DSN existence check under [ODBC Data Sources] only matches entries formatted exactly as Apache Arrow Flight SQL ODBC DSN=.... In many odbc.ini files the = is surrounded by whitespace (e.g., DSN_NAME = Driver), so this can fail to detect an existing entry and insert a duplicate. Consider matching optional whitespace around = (and/or parsing the section more robustly) before inserting.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We now check for possible whitespace.

"${CMAKE_CURRENT_SOURCE_DIR}/install/mac/postinstall")
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/install/mac/README.txt")
set(CPACK_RESOURCE_FILE_WELCOME
"${CMAKE_CURRENT_SOURCE_DIR}/install/mac/Welcome.txt")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use lower case (welcome.txt)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../LICENSE.txt"
DESTINATION "${DOC_INSTALL_DIR}"
COMPONENT Docs)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/Connection-Options.md"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use lower case (connection-options.md)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

else()
if(APPLE)
set(CPACK_PACKAGE_FILE_NAME
"ArrowFlightSqlOdbcODBC-${CPACK_PACKAGE_VERSION_MAJOR}.${ODBC_PACKAGE_VERSION_MINOR}.${ODBC_PACKAGE_VERSION_PATCH}"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the OdbcODBC part intentional?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed to ArrowFlightSqlOdbc

Comment on lines +181 to +184
# GH-49595: TODO implement DEB installer
# GH-47977: TODO implement RPM installer
message(STATUS "ODBC_PACKAGE_FORMAT DEB not implemented, see GH-49595")
message(STATUS "ODBC_PACKAGE_FORMAT RPM not implemented, see GH-47977")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to use CPack for deb and RPM?
I want to use https://github.com/apache/arrow/tree/main/dev/tasks/linux-packages for them.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kou Yes we would like to use CPack for the deb and RPM Linux ODBC installers. The goal is to have deb and rpm installers on Linux that are comparable to the Windows and macOS ODBC installers. By using CPack, we will be able make the installer run ODBC registration scripts and install the docs etc.

I have raised GitHub issues for using linux-packages to create deb and rpm installers:

These are currently unassigned

cc @lidavidm

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @raulcd, as mentioned in the Arrow community meeting, this is the PR thread discussion regarding linux-packages

"${CMAKE_CURRENT_SOURCE_DIR}/install/mac/Welcome.txt")

set(ODBC_INSTALL_DIR "arrow-odbc/lib")
set(DOC_INSTALL_DIR "arrow-odbc/doc")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use ODBC_ prefix?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines +215 to +217
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../LICENSE.txt"
DESTINATION "${DOC_INSTALL_DIR}"
COMPONENT Docs)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LICENSE.txt (and NOTICE.txt) are already installed to ARROW_DOC_DIR. Do we need to install them separately for ODBC?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, a separate install command is needed for ODBC here. During Windows ODBC implementation, we noticed Unspecified components that are not ODBC-related (such as file system stream executables), so we excluded all Unspecified components from the ODBC installer.

I assume we are talking about:

arrow/cpp/CMakeLists.txt

Lines 697 to 699 in acd8e44

install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE.txt
${CMAKE_CURRENT_SOURCE_DIR}/../NOTICE.txt
${CMAKE_CURRENT_SOURCE_DIR}/README.md DESTINATION "${ARROW_DOC_DIR}")

Cmake marks install(... ${ARROW_DOC_DIR}) command as Unspecified since it doesn't set a COMPONENT. Therefore it isn't picked up by the ODBC installer.

@github-actions github-actions Bot added awaiting changes Awaiting changes and removed awaiting review Awaiting review labels Apr 18, 2026
@alinaliBQ
Copy link
Copy Markdown
Collaborator Author

@justing-bq Could you help with addressing the comments here, thank you

@github-actions github-actions Bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Apr 21, 2026
@alinaliBQ alinaliBQ requested a review from kou April 22, 2026 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants