Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNOW-1739603: Implement toml config file parsing #836

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ set(SOURCE_FILES
include/snowflake/version.h
include/snowflake/platform.h
include/snowflake/secure_storage.h
include/snowflake/client_config_parser.h
include/snowflake/client_config_parser.h
lib/client.c
lib/constants.h
lib/cJSON.h
Expand Down Expand Up @@ -158,6 +158,7 @@ set(SOURCE_FILES_CPP_WRAPPER
include/snowflake/IAuth.hpp
include/snowflake/BindUploader.hpp
include/snowflake/SecureStorage.hpp
include/snowflake/TomlConfigParser.hpp
cpp/lib/Exceptions.cpp
cpp/lib/Connection.cpp
cpp/lib/Statement.cpp
Expand All @@ -183,6 +184,7 @@ set(SOURCE_FILES_CPP_WRAPPER
cpp/lib/ClientBindUploader.hpp
cpp/lib/ClientBindUploader.cpp
cpp/lib/client_config_parser.cpp
cpp/lib/TomlConfigParser.cpp
cpp/platform/secure_storage.cpp
cpp/platform/SecureStorage.cpp
cpp/platform/SecureStorageApple.cpp
Expand Down Expand Up @@ -371,6 +373,7 @@ if (LINUX)
deps-build/${PLATFORM}/${CMAKE_BUILD_TYPE}/cmocka/include
deps-build/${PLATFORM}/${CMAKE_BUILD_TYPE}/uuid/include
deps-build/${PLATFORM}/${CMAKE_BUILD_TYPE}/picojson/include
deps-build/${PLATFORM}/${CMAKE_BUILD_TYPE}/tomlplusplus/include
include
lib)
endif()
Expand All @@ -387,6 +390,7 @@ if (APPLE)
deps-build/${PLATFORM}/${CMAKE_BUILD_TYPE}/azure/include
deps-build/${PLATFORM}/${CMAKE_BUILD_TYPE}/cmocka/include
deps-build/${PLATFORM}/${CMAKE_BUILD_TYPE}/picojson/include
deps-build/${PLATFORM}/${CMAKE_BUILD_TYPE}/tomlplusplus/include
include
lib)
endif()
Expand All @@ -402,6 +406,7 @@ if (WIN32)
deps-build/${PLATFORM}/${VSDIR}/${CMAKE_BUILD_TYPE}/azure/include
deps-build/${PLATFORM}/${VSDIR}/${CMAKE_BUILD_TYPE}/cmocka/include
deps-build/${PLATFORM}/${VSDIR}/${CMAKE_BUILD_TYPE}/picojson/include
deps-build/${PLATFORM}/${VSDIR}/${CMAKE_BUILD_TYPE}/tomlplusplus/include
include
lib)
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
Expand Down
1 change: 1 addition & 0 deletions ci/build/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ download_build_component azure "$SCRIPTS_DIR/build_azuresdk.sh" "$target"
download_build_component cmocka "$SCRIPTS_DIR/build_cmocka.sh" "$target"
download_build_component arrow "$SCRIPTS_DIR/build_arrow.sh" "$target"
download_build_component picojson "$SCRIPTS_DIR/build_picojson.sh" "$target"
download_build_component tomlplusplus "$SCRIPTS_DIR/build_tomlplusplus.sh" "$target"

# very tight diskspace limit on github runners, clear deps folder with all .o files
if [[ -n "$GITHUB_ACTIONS" ]]; then
Expand Down
3 changes: 3 additions & 0 deletions ci/build_win.bat
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ set azure_build_script="%scriptdir%..\scripts\build_azuresdk.bat"
set cmocka_build_script="%scriptdir%..\scripts\build_cmocka.bat"
set arrow_build_script="%scriptdir%..\scripts\build_arrow.bat"
set picojson_build_script="%scriptdir%..\scripts\build_picojson.bat"
set tomlplusplus_build_script="%scriptdir%..\scripts\build_tomlplusplus.bat"
set libsnowflakeclient_build_script="%scriptdir%..\scripts\build_libsnowflakeclient.bat"

set upload_artifact_script="%scriptdir%container\upload_artifact.bat"
Expand Down Expand Up @@ -62,6 +63,8 @@ goto :EOF
if %ERRORLEVEL% NEQ 0 goto :error
call :download_build_component picojson "%picojson_build_script%" "%dynamic_runtime%"
if %ERRORLEVEL% NEQ 0 goto :error
call :download_build_component tomlplusplus "%tomlplusplus_build_script%" "%dynamic_runtime%"
if %ERRORLEVEL% NEQ 0 goto :error
if defined GITHUB_ACTIONS (
rd /S /Q %scriptdir%\..\deps
)
Expand Down
107 changes: 107 additions & 0 deletions cpp/lib/TomlConfigParser.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include "snowflake/TomlConfigParser.hpp"
#include "../logger/SFLogger.hpp"
#include "memory.h"

#define TOML_EXCEPTIONS 0
#include <toml++/toml.hpp>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please use #define TOML_EXCEPTIONS 0
https://marzer.github.io/tomlplusplus/#mainpage-example-parsing-without-exceptions

We want to move towards exception free code


#undef snprintf
#include <boost/filesystem.hpp>

namespace
{
using namespace Snowflake::Client;

// constants
const std::string ENV_SNOWFLAKE_HOME = "SNOWFLAKE_HOME";
const std::string ENV_SNOWFLAKE_DEF_CONN_NAME = "SNOWFLAKE_DEFAULT_CONNECTION_NAME";
const std::string SNOWFLAKE_HOME_DIR = ".snowflake";
const std::string TOML_FILENAME = "connections.toml";

// helpers
std::string getEnvironmentVariableValue(const std::string& envVarName) {
// Environment variables being checked point to file paths, hence MAX_PATH is used
char envbuf[MAX_PATH + 1];
if (char* value = sf_getenv_s(envVarName.c_str(), envbuf, sizeof(envbuf))) {
return std::string(value);
}
return "";
}

boost::filesystem::path resolveTomlPath() {
boost::filesystem::path tomlFilePath;
// Check in SNOWFLAKE_HOME
std::string snowflakeHomeEnv = getEnvironmentVariableValue(ENV_SNOWFLAKE_HOME);
if (!snowflakeHomeEnv.empty()) {
tomlFilePath = snowflakeHomeEnv;
tomlFilePath.append(TOML_FILENAME);
} else {
// Check in ~/.snowflake
#if defined(_WIN32) || defined(_WIN64)
std::string homeDir = getEnvironmentVariableValue("USERPROFILE");
if (!homeDir.empty()) {
tomlFilePath = homeDir;
tomlFilePath.append(SNOWFLAKE_HOME_DIR);
tomlFilePath.append(TOML_FILENAME);
} else {
// USERPROFILE is empty, try HOMEDRIVE and HOMEPATH
std::string homeDriveEnv = getEnvironmentVariableValue("HOMEDRIVE");
std::string homePathEnv = getEnvironmentVariableValue("HOMEPATH");
if (!homeDriveEnv.empty() && !homePathEnv.empty()) {
tomlFilePath = std::string(homeDriveEnv) + homePathEnv;
tomlFilePath.append(SNOWFLAKE_HOME_DIR);
tomlFilePath.append(TOML_FILENAME);
}
}
#else
std::string homeDir = getEnvironmentVariableValue("HOME");
if (!homeDir.empty()) {
tomlFilePath = homeDir;
tomlFilePath.append(SNOWFLAKE_HOME_DIR);
tomlFilePath.append(TOML_FILENAME);
}
#endif
}
return tomlFilePath;
}

std::map<std::string, std::string> parseTomlFile(
const boost::filesystem::path& filePath) {
std::map<std::string, std::string> connectionParams;
toml::parse_result result = toml::parse_file(filePath.c_str());
if (!result)
{
CXX_LOG_ERROR("Failed to parse toml file: %s. Error: %s", filePath.c_str(), result.error().description().data());
return connectionParams;
}
toml::table table = std::move(result).table();
std::string configurationName = getEnvironmentVariableValue(ENV_SNOWFLAKE_DEF_CONN_NAME);
if (configurationName.empty()) {
configurationName = "default";
}
toml::node_view config = table[configurationName];
if (!config) {
CXX_LOG_ERROR("Could not find connection configuration name %s in toml file.", configurationName.c_str());
return connectionParams;
}
for (auto [key, val] : *config.as_table()) {
connectionParams[key.data()] = val.as_string()->get();
}
return connectionParams;
}
}

std::map<std::string, std::string> load_toml_config()
{
std::map<std::string, std::string> params;
// Disable toml config parsing for 32-bit windows debug build due to linking issues
// with _osfile causing hanging/assertions until dynamic linking is available
#if (!defined(_WIN32) && !defined(_DEBUG)) || defined(_WIN64)
boost::filesystem::path derivedTomlFilePath = resolveTomlPath();

if (!derivedTomlFilePath.empty()) {
params = parseTomlFile(derivedTomlFilePath);
}
#endif
return params;
}
Loading