From 7a41c5f8574b17e0b3ec27a5e956157a3802b1c3 Mon Sep 17 00:00:00 2001 From: James Duong Date: Thu, 1 Dec 2022 16:53:27 -0800 Subject: [PATCH 001/195] Add Session management messages, Location URI path accessors Messages and handlers for SetSessionOptions, GetSessionOptions, and CloseSession added. Parsing logic and accessors for Location URI path component added, as raw path and as request headers. --- cpp/src/arrow/flight/sql/client.cc | 151 ++++++++++++++++++++++ cpp/src/arrow/flight/sql/client.h | 19 +++ cpp/src/arrow/flight/sql/server.cc | 200 +++++++++++++++++++++++++++++ cpp/src/arrow/flight/sql/server.h | 57 ++++++++ cpp/src/arrow/flight/sql/types.h | 29 +++++ cpp/src/arrow/flight/types.cc | 28 ++++ cpp/src/arrow/flight/types.h | 9 ++ format/FlightSql.proto | 88 +++++++++++++ 8 files changed, 581 insertions(+) diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index d0552e33df5c2..059f43b54f3d3 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -797,6 +797,157 @@ ::arrow::Result FlightSqlClient::CancelQuery( return Status::IOError("Server returned unknown result ", result.result()); } +::arrow::Result> FlightSqlClient::SetSessionOptions( + const FlightCallOptions& options, + const std::vector& session_options) { + flight_sql_pb::ActionSetSessionOptionsRequest request; + for (const SessionOption& in_opt : session_options) { + flight_sql_pb::SessionOption& opt = *request.add_session_options(); + const std::string& name = in_opt.option_name; + opt.set_option_name(name); + + const SessionOptionValue& value = in_opt.option_value; + if (value.index() == std::variant_npos) + return Status::Invalid("Undefined SessionOptionValue type "); + switch ((SessionOptionValueType)(value.index())) { + case SessionOptionValueType::kString: + opt.set_string_value(std::get(value)); + break; + case SessionOptionValueType::kBool: + opt.set_bool_value(std::get(value)); + break; + case SessionOptionValueType::kInt32: + opt.set_int32_value(std::get(value)); + break; + case SessionOptionValueType::kInt64: + opt.set_int64_value(std::get(value)); + break; + case SessionOptionValueType::kFloat: + opt.set_float_value(std::get(value)); + break; + case SessionOptionValueType::kDouble: + opt.set_double_value(std::get(value)); + break; + case SessionOptionValueType::kStringList: + flight_sql_pb::SessionOption::StringListValue& string_list_value = + *opt.mutable_string_list_value(); + for (const std::string& s : std::get>(value)) + string_list_value.add_values(s); + break; + } + } + + std::unique_ptr results; + ARROW_ASSIGN_OR_RAISE(auto action, PackAction("SetSessionOptions", request)); + ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); + + flight_sql_pb::ActionSetSessionOptionsResult pb_result; + ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); + ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); + std::vector result; + for (const int result_value : pb_result.results()) { + switch (result_value) { + case flight_sql_pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED: + result.push_back(SetSessionOptionResult::kUnspecified); + break; + case flight_sql_pb::ActionSetSessionOptionsResult + ::SET_SESSION_OPTION_RESULT_OK: + result.push_back(SetSessionOptionResult::kOk); + break; + case flight_sql_pb::ActionSetSessionOptionsResult + ::SET_SESSION_OPTION_RESULT_INVALID_VALUE: + result.push_back(SetSessionOptionResult::kInvalidResult); + break; + case flight_sql_pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR: + result.push_back(SetSessionOptionResult::kError); + break; + } + } + + return result; +} + +::arrow::Result> FlightSqlClient::GetSessionOptions ( + const FlightCallOptions& options) { + flight_sql_pb::ActionGetSessionOptionsRequest request; + + std::unique_ptr results; + ARROW_ASSIGN_OR_RAISE(auto action, PackAction("GetSessionOptions", request)); + ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); + + flight_sql_pb::ActionGetSessionOptionsResult pb_result; + ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); + ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); + + std::vector result; + if (pb_result.session_options_size() > 0) { + result.reserve(pb_result.session_options_size()); + for (const flight_sql_pb::SessionOption& in_opt : pb_result.session_options()) { + const std::string& name = in_opt.option_name(); + SessionOption opt; + switch (in_opt.option_value_case()) { + case flight_sql_pb::SessionOption::OPTION_VALUE_NOT_SET: + return Status::Invalid("Unset option_value for name '" + name + "'"); + case flight_sql_pb::SessionOption::kStringValue: + opt = {name, in_opt.string_value()}; + break; + case flight_sql_pb::SessionOption::kBoolValue: + opt = {name, in_opt.bool_value()}; + break; + case flight_sql_pb::SessionOption::kInt32Value: + opt = {name, in_opt.int32_value()}; + break; + case flight_sql_pb::SessionOption::kInt64Value: + opt = {name, in_opt.int64_value()}; + break; + case flight_sql_pb::SessionOption::kFloatValue: + opt = {name, in_opt.float_value()}; + break; + case flight_sql_pb::SessionOption::kDoubleValue: + opt = {name, in_opt.double_value()}; + break; + case flight_sql_pb::SessionOption::kStringListValue: + std::vector vlist; + vlist.reserve(in_opt.string_list_value().values_size()); + for (const std::string& s : in_opt.string_list_value().values()) + vlist.push_back(s); + opt = {name, vlist}; + break; + } + result.push_back(opt); + } + } + + return result; +} + +::arrow::Result FlightSqlClient::CloseSession( + const FlightCallOptions& options) { + flight_sql_pb::ActionCloseSessionRequest request; + + std::unique_ptr results; + ARROW_ASSIGN_OR_RAISE(auto action, PackAction("CloseSession", request)); + ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); + + flight_sql_pb::ActionCloseSessionResult result; + ARROW_RETURN_NOT_OK(ReadResult(results.get(), &result)); + ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); + switch (result.result()) { + case flight_sql_pb::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED: + return CloseSessionResult::kUnspecified; + case flight_sql_pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSED: + return CloseSessionResult::kClosed; + case flight_sql_pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSING: + return CloseSessionResult::kClosing; + case flight_sql_pb::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE: + return CloseSessionResult::kNotClosable; + default: + break; + } + + return Status::IOError("Server returned unknown result ", result.result()); +} + Status FlightSqlClient::Close() { return impl_->Close(); } std::ostream& operator<<(std::ostream& os, CancelResult result) { diff --git a/cpp/src/arrow/flight/sql/client.h b/cpp/src/arrow/flight/sql/client.h index 5f3fc7d8574a9..3cdcc81aa72ae 100644 --- a/cpp/src/arrow/flight/sql/client.h +++ b/cpp/src/arrow/flight/sql/client.h @@ -349,6 +349,25 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlClient { "may need to use CancelQuery() and/or CancelFlightInfo()") ::arrow::Result CancelQuery(const FlightCallOptions& options, const FlightInfo& info); + + /// \brief Sets session options. + /// + /// \param[in] options RPC-layer hints for this call. + /// \param[in] session_options The session options to set. + ::arrow::Result> SetSessionOptions( + const FlightCallOptions& options, + const std::vector& session_options); + + /// \brief Gets current session options. + /// + /// \param[in] options RPC-layer hints for this call. + ::arrow::Result> GetSessionOptions( + const FlightCallOptions& options); + + /// \brief Explicitly closes the session if applicable. + /// + /// \param[in] options RPC-layer hints for this call. + ::arrow::Result CloseSession(const FlightCallOptions& options); /// \brief Extends the expiration of a FlightEndpoint. /// diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index a6d197d15b2c0..1979876dcfcd3 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -270,6 +270,17 @@ arrow::Result ParseActionCancelQueryRequest( return result; } +arrow::Result ParseActionCloseSessionRequest( + const google::protobuf::Any& any) { + pb::sql::ActionCloseSessionRequest command; + if (!any.UnpackTo(&command)) { + return Status::Invalid("Unable to unpack ActionCloseSessionRequest"); + } + + ActionCloseSessionRequest result; + return result; +} + arrow::Result ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) { pb::sql::ActionCreatePreparedStatementRequest command; @@ -360,6 +371,66 @@ arrow::Result ParseActionEndTransactionRequest( return result; } +arrow::Result ParseActionSetSessionOptionsRequest( + const google::protobuf::Any& any) { + pb::sql::ActionSetSessionOptionsRequest command; + if (!any.UnpackTo(&command)) { + return Status::Invalid("Unable to unpack ActionSetSessionOptionsRequest"); + } + + ActionSetSessionOptionsRequest result; + if (command.session_options_size() > 0) { + result.session_options.reserve(command.session_options_size()); + for (const pb::sql::SessionOption& in_opt : command.session_options()) { + const std::string& name = in_opt.option_name(); + SessionOption opt; + switch (in_opt.option_value_case()) { + case pb::sql::SessionOption::OPTION_VALUE_NOT_SET: + return Status::Invalid("Unset SessionOptionValue for name '" + name + "'"); + case pb::sql::SessionOption::kStringValue: + opt = {name, in_opt.string_value()}; + break; + case pb::sql::SessionOption::kBoolValue: + opt = {name, in_opt.bool_value()}; + break; + case pb::sql::SessionOption::kInt32Value: + opt = {name, in_opt.int32_value()}; + break; + case pb::sql::SessionOption::kInt64Value: + opt = {name, in_opt.int64_value()}; + break; + case pb::sql::SessionOption::kFloatValue: + opt = {name, in_opt.float_value()}; + break; + case pb::sql::SessionOption::kDoubleValue: + opt = {name, in_opt.double_value()}; + break; + case pb::sql::SessionOption::kStringListValue: + std::vector vlist; + vlist.reserve(in_opt.string_list_value().values_size()); + for (const std::string& s : in_opt.string_list_value().values()) + vlist.push_back(s); + opt = {name, vlist}; + break; + } + result.session_options.push_back(opt); + } + } + + return result; +} + +arrow::Result ParseActionGetSessionOptionsRequest( + const google::protobuf::Any& any) { + pb::sql::ActionGetSessionOptionsRequest command; + if (!any.UnpackTo(&command)) { + return Status::Invalid("Unable to unpack ActionGetSessionOptionsRequest"); + } + + ActionGetSessionOptionsRequest result; + return result; +} + arrow::Result PackActionResult(const google::protobuf::Message& message) { google::protobuf::Any any; #if PROTOBUF_VERSION >= 3015000 @@ -442,6 +513,91 @@ arrow::Result PackActionResult(ActionCreatePreparedStatementResult resul return PackActionResult(pb_result); } +arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { + pb::sql::ActionSetSessionOptionsResult pb_result; + for (SetSessionOptionResult& res : result.results) { + switch (res) { + case SetSessionOptionResult::kUnspecified: + pb_result.add_results( + pb::sql::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED); + break; + case SetSessionOptionResult::kOk: + pb_result.add_results( + pb::sql::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_OK); + break; + case SetSessionOptionResult::kInvalidResult: + pb_result.add_results( + pb::sql::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_INVALID_VALUE); + break; + case SetSessionOptionResult::kError: + pb_result.add_results( + pb::sql::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR); + break; + } + } + return PackActionResult(pb_result); +} + +arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { + pb::sql::ActionGetSessionOptionsResult pb_result; + for (const SessionOption& in_opt : result.session_options) { + pb::sql::SessionOption& opt = *pb_result.add_session_options(); + const std::string& name = in_opt.option_name; + opt.set_option_name(name); + + const SessionOptionValue& value = in_opt.option_value; + if (value.index() == std::variant_npos) + return Status::Invalid("Undefined SessionOptionValue type "); + switch ((SessionOptionValueType)(value.index())) { + case SessionOptionValueType::kString: + opt.set_string_value(std::get(value)); + break; + case SessionOptionValueType::kBool: + opt.set_bool_value(std::get(value)); + break; + case SessionOptionValueType::kInt32: + opt.set_int32_value(std::get(value)); + break; + case SessionOptionValueType::kInt64: + opt.set_int64_value(std::get(value)); + break; + case SessionOptionValueType::kFloat: + opt.set_float_value(std::get(value)); + break; + case SessionOptionValueType::kDouble: + opt.set_double_value(std::get(value)); + break; + case SessionOptionValueType::kStringList: + pb::sql::SessionOption::StringListValue& string_list_value = + *opt.mutable_string_list_value(); + for (const std::string& s : std::get>(value)) + string_list_value.add_values(s); + break; + } + } + + return PackActionResult(pb_result); +} + +arrow::Result PackActionResult(CloseSessionResult result) { + pb::sql::ActionCloseSessionResult pb_result; + switch (result) { + case CloseSessionResult::kUnspecified: + pb_result.set_result(pb::sql::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED); + break; + case CloseSessionResult::kClosed: + pb_result.set_result(pb::sql::ActionCloseSessionResult::CLOSE_RESULT_CLOSED); + break; + case CloseSessionResult::kClosing: + pb_result.set_result(pb::sql::ActionCloseSessionResult::CLOSE_RESULT_CLOSING); + break; + case CloseSessionResult::kNotClosable: + pb_result.set_result(pb::sql::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE); + break; + } + return PackActionResult(pb_result); +} + } // namespace arrow::Result StatementQueryTicket::Deserialize( @@ -768,8 +924,11 @@ Status FlightSqlServerBase::ListActions(const ServerCallContext& context, FlightSqlServerBase::kCreatePreparedStatementActionType, FlightSqlServerBase::kCreatePreparedSubstraitPlanActionType, FlightSqlServerBase::kClosePreparedStatementActionType, + FlightSqlServerBase::kCloseSessionActionType, FlightSqlServerBase::kEndSavepointActionType, FlightSqlServerBase::kEndTransactionActionType, + FlightSqlServerBase::kSetSessionOptionsActionType, + FlightSqlServerBase::kGetSessionOptionsActionType }; return Status::OK(); } @@ -791,6 +950,29 @@ Status FlightSqlServerBase::DoAction(const ServerCallContext& context, ARROW_ASSIGN_OR_RAISE(auto renewed_endpoint, RenewFlightEndpoint(context, request)); ARROW_ASSIGN_OR_RAISE(auto packed_result, PackActionResult(renewed_endpoint)); + results.push_back(std::move(packed_result)); + } else if (action.type == FlightSqlServerBase::kCloseSessionActionType.type) { + ARROW_ASSIGN_OR_RAISE(ActionCloseSessionRequest internal_command, + ParseActionCloseSessionRequest(any)); + ARROW_ASSIGN_OR_RAISE(CloseSessionResult result, CloseSession(context, internal_command)); + ARROW_ASSIGN_OR_RAISE(Result packed_result, PackActionResult(std::move(result))); + + results.push_back(std::move(packed_result)); + } else if (action.type == FlightSqlServerBase::kSetSessionOptionsActionType.type) { + ARROW_ASSIGN_OR_RAISE(ActionSetSessionOptionsRequest internal_command, + ParseActionSetSessionOptionsRequest(any)); + ARROW_ASSIGN_OR_RAISE(ActionSetSessionOptionsResult result, + SetSessionOptions(context, internal_command)); + ARROW_ASSIGN_OR_RAISE(Result packed_result, PackActionResult(std::move(result))); + + results.push_back(std::move(packed_result)); + } else if (action.type == FlightSqlServerBase::kGetSessionOptionsActionType.type) { + ARROW_ASSIGN_OR_RAISE(ActionGetSessionOptionsRequest internal_command, + ParseActionGetSessionOptionsRequest(any)); + ARROW_ASSIGN_OR_RAISE(ActionGetSessionOptionsResult result, + GetSessionOptions(context, internal_command)); + ARROW_ASSIGN_OR_RAISE(Result packed_result, PackActionResult(std::move(result))); + results.push_back(std::move(packed_result)); } else { google::protobuf::Any any; @@ -1098,6 +1280,12 @@ arrow::Result FlightSqlServerBase::RenewFlightEndpoint( return Status::NotImplemented("RenewFlightEndpoint not implemented"); } +arrow::Result FlightSqlServerBase::CloseSession( + const ServerCallContext& context, + const ActionCloseSessionRequest& request) { + return Status::NotImplemented("CloseSession not implemented"); +} + arrow::Result FlightSqlServerBase::CreatePreparedStatement( const ServerCallContext& context, @@ -1128,6 +1316,18 @@ Status FlightSqlServerBase::EndTransaction(const ServerCallContext& context, return Status::NotImplemented("EndTransaction not implemented"); } +arrow::Result FlightSqlServerBase::SetSessionOptions ( + const ServerCallContext& context, + const ActionSetSessionOptionsRequest& request) { + return Status::NotImplemented("SetSessionOptions not implemented"); +} + +arrow::Result FlightSqlServerBase::GetSessionOptions ( + const ServerCallContext& context, + const ActionGetSessionOptionsRequest& request) { + return Status::NotImplemented("GetSessionOptions not implemented"); +} + Status FlightSqlServerBase::DoPutPreparedStatementQuery( const ServerCallContext& context, const PreparedStatementQuery& command, FlightMessageReader* reader, FlightMetadataWriter* writer) { diff --git a/cpp/src/arrow/flight/sql/server.h b/cpp/src/arrow/flight/sql/server.h index 24f0aa2bd48cf..bbd3a73773d66 100644 --- a/cpp/src/arrow/flight/sql/server.h +++ b/cpp/src/arrow/flight/sql/server.h @@ -225,6 +225,27 @@ struct ARROW_FLIGHT_SQL_EXPORT ActionCreatePreparedStatementResult { std::string prepared_statement_handle; }; +/// \brief A request to close the open client session. +struct ARROW_FLIGHT_SQL_EXPORT ActionCloseSessionRequest {}; + +/// \brief A request to set a set of session options by key/value. +struct ARROW_FLIGHT_SQL_EXPORT ActionSetSessionOptionsRequest { + std::vector session_options; +}; + +/// \brief The result(s) of setting session option(s). +struct ARROW_FLIGHT_SQL_EXPORT ActionSetSessionOptionsResult { + std::vector results; +}; + +/// \brief A request to get current session options. +struct ARROW_FLIGHT_SQL_EXPORT ActionGetSessionOptionsRequest {}; + +/// \brief The current session options. +struct ARROW_FLIGHT_SQL_EXPORT ActionGetSessionOptionsResult { + std::vector session_options; +}; + /// @} /// \brief A utility function to create a ticket (a opaque binary @@ -601,6 +622,27 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlServerBase : public FlightServerBase { virtual arrow::Result CancelFlightInfo( const ServerCallContext& context, const CancelFlightInfoRequest& request); + /// \brief Set server session option(s). + /// \param[in] context The call context. + /// \param[in] request The session options to set. + virtual arrow::Result SetSessionOptions( + const ServerCallContext& context, + const ActionSetSessionOptionsRequest& request); + + /// \brief Get server session option(s). + /// \param[in] context The call context. + /// \param[in] request Request object. + virtual arrow::Result GetSessionOptions( + const ServerCallContext& context, + const ActionGetSessionOptionsRequest& request); + + /// \brief Close/invalidate the session. + /// \param[in] context The call context. + /// \param[in] request Request object. + virtual arrow::Result CloseSession( + const ServerCallContext& context, + const ActionCloseSessionRequest& request); + /// \brief Attempt to explicitly cancel a query. /// /// \param[in] context The call context. @@ -682,6 +724,11 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlServerBase : public FlightServerBase { "Closes a reusable prepared statement resource on the server.\n" "Request Message: ActionClosePreparedStatementRequest\n" "Response Message: N/A"}; + const ActionType kCloseSessionActionType = + ActionType{"CloseSession", + "Explicitly close an open session.\n" + "Request Message: ActionCloseSessionRequest\n" + "Response Message: ActionCloseSessionResult"}; const ActionType kEndSavepointActionType = ActionType{"EndSavepoint", "End a savepoint.\n" @@ -692,6 +739,16 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlServerBase : public FlightServerBase { "End a savepoint.\n" "Request Message: ActionEndTransactionRequest\n" "Response Message: N/A"}; + const ActionType kSetSessionOptionsActionType = + ActionType{"SetSessionOptions", + "Set a series of session options.\n" + "Request Message: ActionSetSessionOptionsRequest\n" + "Response Message: ActionSetSessionOptionsResult"}; + const ActionType kGetSessionOptionsActionType = + ActionType{"GetSessionOption", + "Get a series of session options.\n" + "Request Message: ActionGetSessionOptionRequest\n" + "Response Message: ActionGetSessionOptionResult"}; Status ListActions(const ServerCallContext& context, std::vector* actions) final; diff --git a/cpp/src/arrow/flight/sql/types.h b/cpp/src/arrow/flight/sql/types.h index b41488b68f232..d623650f5a936 100644 --- a/cpp/src/arrow/flight/sql/types.h +++ b/cpp/src/arrow/flight/sql/types.h @@ -44,6 +44,19 @@ using SqlInfoResult = /// \brief Map SQL info identifier to its value. using SqlInfoResultMap = std::unordered_map; +/// \brief Variant supporting all possible types for SetSessionOption +using SessionOptionValue = + std::variant>; + +enum struct SessionOptionValueType : size_t { + kString, kBool, kInt32, kInt64, kFloat, kDouble, kStringList +}; + +struct ARROW_FLIGHT_SQL_EXPORT SessionOption { + std::string option_name; + SessionOptionValue option_value; +}; + /// \brief Options to be set in the SqlInfo. struct ARROW_FLIGHT_SQL_EXPORT SqlInfoOptions { /// \brief Predefined info values for GetSqlInfo. @@ -920,6 +933,22 @@ enum class CancelResult : int8_t { kNotCancellable, }; +/// \brief The result of setting a session option. +enum class SetSessionOptionResult : int8_t { + kUnspecified, + kOk, + kInvalidResult, + kError +}; + +/// \brief The result of closing a session. +enum class CloseSessionResult : int8_t { + kUnspecified, + kClosed, + kClosing, + kNotClosable +}; + ARROW_FLIGHT_SQL_EXPORT std::ostream& operator<<(std::ostream& os, CancelResult result); diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 1d43c41b69d9f..ae28a6a331325 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -516,6 +516,34 @@ std::string Location::scheme() const { return scheme; } +std::string Location::path() const { return uri_->path(); } +arrow::Result>> Location::query_items() + const { + return uri_->query_items(); +} + +arrow::Result>> Location::as_headers() + const { + std::string catalog = path(); + if (catalog.empty()) { + return query_items(); + } + + std::vector> headers; + + auto query_items_result = query_items(); + if (!query_items_result.ok()) { + return query_items_result; + } + std::vector> items(*query_items_result); + headers.reserve(items.size() + 1); + + headers.emplace_back(std::pair("catalog", catalog)); + headers.insert(headers.end(), items.begin(), items.end()); + + return headers; +} + bool Location::Equals(const Location& other) const { return ToString() == other.ToString(); } diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 790a2067dd705..5b37bed25b7c4 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -450,6 +450,15 @@ struct ARROW_FLIGHT_EXPORT Location { /// \brief Get the scheme of this URI. std::string scheme() const; + /// \brief Get the path of this URI. + std::string path() const; + + /// \brief Get the query parameters of this URI. + arrow::Result>> query_items() const; + + /// \brief Convert URI path and parameters to headers. + arrow::Result>> as_headers() const; + bool Equals(const Location& other) const; friend bool operator==(const Location& left, const Location& right) { diff --git a/format/FlightSql.proto b/format/FlightSql.proto index 581cf1f76d57c..4aa3a47c9d27b 100644 --- a/format/FlightSql.proto +++ b/format/FlightSql.proto @@ -1856,6 +1856,94 @@ message ActionCancelQueryResult { CancelResult result = 1; } +/* + * Request message for the "Close Session" action. + */ +message ActionCloseSessionRequest { + option (experimental) = true; +} + +/* + * The result of closing a session. + * + * The result should be wrapped in a google.protobuf.Any message. + */ +message ActionCloseSessionResult { + option (experimental) = true; + + enum CloseSessionResult { + // The cancellation status is unknown. Servers should avoid using + // this value (send a NOT_FOUND error if the requested query is + // not known). Clients can retry the request. + CLOSE_RESULT_UNSPECIFIED = 0; + // The session close request is complete. Subsequent requests with + // a NOT_FOUND error. + CLOSE_RESULT_CLOSED = 1; + // The session close request is in progress. The client may retry + // the close request. + CLOSE_RESULT_CLOSING = 2; + // The session is not closeable. The client should not retry the + // close request. + CLOSE_RESULT_NOT_CLOSEABLE = 3; + } + + CloseSessionResult result = 1; +} + +message SessionOption { + option (experimental) = true; + + message StringListValue { + repeated string values = 1; + } + + string option_name = 1; + oneof option_value { + string string_value = 2; + bool bool_value = 3; + sfixed32 int32_value = 4; + sfixed64 int64_value = 5; + float float_value = 6; + double double_value = 7; + StringListValue string_list_value = 8; + } +} + +message ActionSetSessionOptionsRequest { + option (experimental) = true; + + repeated SessionOption session_options = 1; +} + +message ActionSetSessionOptionsResult { + option (experimental) = true; + + enum SetSessionOptionResult { + // The status of setting the option is unknown. Servers should avoid using + // this value (send a NOT_FOUND error if the requested query is + // not known). Clients can retry the request. + SET_SESSION_OPTION_RESULT_UNSPECIFIED = 0; + // The session option setting completed successfully. + SET_SESSION_OPTION_RESULT_OK = 1; + // The session cannot be set to the given value. + SET_SESSION_OPTION_RESULT_INVALID_VALUE = 2; + // The session cannot be set. + SET_SESSION_OPTION_RESULT_ERROR = 3; + } + + repeated SetSessionOptionResult results = 1; +} + +message ActionGetSessionOptionsRequest { + option (experimental) = true; +} + +message ActionGetSessionOptionsResult { + option (experimental) = true; + + repeated SessionOption session_options = 1; +} + extend google.protobuf.MessageOptions { bool experimental = 1000; } From dbbc8298a4e09841c88554c49ac104f06f73845f Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 3 Apr 2023 11:57:10 -0700 Subject: [PATCH 002/195] Address PR feedback --- cpp/src/arrow/flight/sql/client.cc | 26 +++++++++++++------------- cpp/src/arrow/flight/sql/server.cc | 24 ++++++++++++------------ cpp/src/arrow/flight/sql/types.h | 4 ++++ cpp/src/arrow/flight/types.cc | 8 ++++---- cpp/src/arrow/flight/types.h | 4 ++-- format/FlightSql.proto | 2 +- 6 files changed, 36 insertions(+), 32 deletions(-) diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index 059f43b54f3d3..185d0bf81a46b 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -809,7 +809,7 @@ ::arrow::Result> FlightSqlClient::SetSession const SessionOptionValue& value = in_opt.option_value; if (value.index() == std::variant_npos) return Status::Invalid("Undefined SessionOptionValue type "); - switch ((SessionOptionValueType)(value.index())) { + switch (static_cast(value.index())) { case SessionOptionValueType::kString: opt.set_string_value(std::get(value)); break; @@ -884,37 +884,37 @@ ::arrow::Result> FlightSqlClient::GetSessionOptions ( result.reserve(pb_result.session_options_size()); for (const flight_sql_pb::SessionOption& in_opt : pb_result.session_options()) { const std::string& name = in_opt.option_name(); - SessionOption opt; + SessionOptionValue val; switch (in_opt.option_value_case()) { case flight_sql_pb::SessionOption::OPTION_VALUE_NOT_SET: return Status::Invalid("Unset option_value for name '" + name + "'"); case flight_sql_pb::SessionOption::kStringValue: - opt = {name, in_opt.string_value()}; + val = in_opt.string_value(); break; case flight_sql_pb::SessionOption::kBoolValue: - opt = {name, in_opt.bool_value()}; + val = in_opt.bool_value(); break; case flight_sql_pb::SessionOption::kInt32Value: - opt = {name, in_opt.int32_value()}; + val = in_opt.int32_value(); break; case flight_sql_pb::SessionOption::kInt64Value: - opt = {name, in_opt.int64_value()}; + val = in_opt.int64_value(); break; case flight_sql_pb::SessionOption::kFloatValue: - opt = {name, in_opt.float_value()}; + val = in_opt.float_value(); break; case flight_sql_pb::SessionOption::kDoubleValue: - opt = {name, in_opt.double_value()}; + val = in_opt.double_value(); break; case flight_sql_pb::SessionOption::kStringListValue: - std::vector vlist; - vlist.reserve(in_opt.string_list_value().values_size()); + val.emplace>(); + std::get>(val) + .reserve(in_opt.string_list_value().values_size()); for (const std::string& s : in_opt.string_list_value().values()) - vlist.push_back(s); - opt = {name, vlist}; + std::get>(val).push_back(s); break; } - result.push_back(opt); + result.emplace_back(name, std::move(val)); } } diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index 1979876dcfcd3..5f5f28b245a5c 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -383,37 +383,37 @@ arrow::Result ParseActionSetSessionOptionsReques result.session_options.reserve(command.session_options_size()); for (const pb::sql::SessionOption& in_opt : command.session_options()) { const std::string& name = in_opt.option_name(); - SessionOption opt; + SessionOptionValue val; switch (in_opt.option_value_case()) { case pb::sql::SessionOption::OPTION_VALUE_NOT_SET: return Status::Invalid("Unset SessionOptionValue for name '" + name + "'"); case pb::sql::SessionOption::kStringValue: - opt = {name, in_opt.string_value()}; + val = in_opt.string_value(); break; case pb::sql::SessionOption::kBoolValue: - opt = {name, in_opt.bool_value()}; + val = in_opt.bool_value(); break; case pb::sql::SessionOption::kInt32Value: - opt = {name, in_opt.int32_value()}; + val = in_opt.int32_value(); break; case pb::sql::SessionOption::kInt64Value: - opt = {name, in_opt.int64_value()}; + val = in_opt.int64_value(); break; case pb::sql::SessionOption::kFloatValue: - opt = {name, in_opt.float_value()}; + val = in_opt.float_value(); break; case pb::sql::SessionOption::kDoubleValue: - opt = {name, in_opt.double_value()}; + val = in_opt.double_value(); break; case pb::sql::SessionOption::kStringListValue: - std::vector vlist; - vlist.reserve(in_opt.string_list_value().values_size()); + val.emplace>(); + std::get>(val) + .reserve(in_opt.string_list_value().values_size()); for (const std::string& s : in_opt.string_list_value().values()) - vlist.push_back(s); - opt = {name, vlist}; + std::get>(val).push_back(s); break; } - result.session_options.push_back(opt); + result.session_options.emplace_back(name, std::move(val)); } } diff --git a/cpp/src/arrow/flight/sql/types.h b/cpp/src/arrow/flight/sql/types.h index d623650f5a936..b216f47b6bbb4 100644 --- a/cpp/src/arrow/flight/sql/types.h +++ b/cpp/src/arrow/flight/sql/types.h @@ -55,6 +55,10 @@ enum struct SessionOptionValueType : size_t { struct ARROW_FLIGHT_SQL_EXPORT SessionOption { std::string option_name; SessionOptionValue option_value; + + SessionOption(std::string name, SessionOptionValue val) + : option_name{ name }, option_value{ val } {} + SessionOption() {} }; /// \brief Options to be set in the SqlInfo. diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index ae28a6a331325..1f65b24595b26 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -517,21 +517,21 @@ std::string Location::scheme() const { } std::string Location::path() const { return uri_->path(); } -arrow::Result>> Location::query_items() +arrow::Result>> Location::QueryItems() const { return uri_->query_items(); } -arrow::Result>> Location::as_headers() +arrow::Result>> Location::AsHeaders() const { std::string catalog = path(); if (catalog.empty()) { - return query_items(); + return QueryItems(); } std::vector> headers; - auto query_items_result = query_items(); + auto query_items_result = QueryItems(); if (!query_items_result.ok()) { return query_items_result; } diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 5b37bed25b7c4..c5299d25882b0 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -454,10 +454,10 @@ struct ARROW_FLIGHT_EXPORT Location { std::string path() const; /// \brief Get the query parameters of this URI. - arrow::Result>> query_items() const; + arrow::Result>> QueryItems() const; /// \brief Convert URI path and parameters to headers. - arrow::Result>> as_headers() const; + arrow::Result>> AsHeaders() const; bool Equals(const Location& other) const; diff --git a/format/FlightSql.proto b/format/FlightSql.proto index 4aa3a47c9d27b..840a22eff9983 100644 --- a/format/FlightSql.proto +++ b/format/FlightSql.proto @@ -1872,7 +1872,7 @@ message ActionCloseSessionResult { option (experimental) = true; enum CloseSessionResult { - // The cancellation status is unknown. Servers should avoid using + // The session close status is unknown. Servers should avoid using // this value (send a NOT_FOUND error if the requested query is // not known). Clients can retry the request. CLOSE_RESULT_UNSPECIFIED = 0; From 6738a4966c97a3af37210306539db5ffe124cce7 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 16 Apr 2023 10:24:43 -0700 Subject: [PATCH 003/195] Remove non-const references --- cpp/src/arrow/flight/sql/client.cc | 22 +++++++++++----------- cpp/src/arrow/flight/sql/server.cc | 24 ++++++++++++------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index 185d0bf81a46b..6dd2bc58341ad 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -802,37 +802,37 @@ ::arrow::Result> FlightSqlClient::SetSession const std::vector& session_options) { flight_sql_pb::ActionSetSessionOptionsRequest request; for (const SessionOption& in_opt : session_options) { - flight_sql_pb::SessionOption& opt = *request.add_session_options(); + flight_sql_pb::SessionOption* opt = request.add_session_options(); const std::string& name = in_opt.option_name; - opt.set_option_name(name); + opt->set_option_name(name); const SessionOptionValue& value = in_opt.option_value; if (value.index() == std::variant_npos) return Status::Invalid("Undefined SessionOptionValue type "); switch (static_cast(value.index())) { case SessionOptionValueType::kString: - opt.set_string_value(std::get(value)); + opt->set_string_value(std::get(value)); break; case SessionOptionValueType::kBool: - opt.set_bool_value(std::get(value)); + opt->set_bool_value(std::get(value)); break; case SessionOptionValueType::kInt32: - opt.set_int32_value(std::get(value)); + opt->set_int32_value(std::get(value)); break; case SessionOptionValueType::kInt64: - opt.set_int64_value(std::get(value)); + opt->set_int64_value(std::get(value)); break; case SessionOptionValueType::kFloat: - opt.set_float_value(std::get(value)); + opt->set_float_value(std::get(value)); break; case SessionOptionValueType::kDouble: - opt.set_double_value(std::get(value)); + opt->set_double_value(std::get(value)); break; case SessionOptionValueType::kStringList: - flight_sql_pb::SessionOption::StringListValue& string_list_value = - *opt.mutable_string_list_value(); + flight_sql_pb::SessionOption::StringListValue* string_list_value = + opt->mutable_string_list_value(); for (const std::string& s : std::get>(value)) - string_list_value.add_values(s); + string_list_value->add_values(s); break; } } diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index 5f5f28b245a5c..8176a6d4f87c2 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -515,7 +515,7 @@ arrow::Result PackActionResult(ActionCreatePreparedStatementResult resul arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { pb::sql::ActionSetSessionOptionsResult pb_result; - for (SetSessionOptionResult& res : result.results) { + for (const SetSessionOptionResult res : result.results) { switch (res) { case SetSessionOptionResult::kUnspecified: pb_result.add_results( @@ -541,37 +541,37 @@ arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { pb::sql::ActionGetSessionOptionsResult pb_result; for (const SessionOption& in_opt : result.session_options) { - pb::sql::SessionOption& opt = *pb_result.add_session_options(); + pb::sql::SessionOption* opt = pb_result.add_session_options(); const std::string& name = in_opt.option_name; - opt.set_option_name(name); + opt->set_option_name(name); const SessionOptionValue& value = in_opt.option_value; if (value.index() == std::variant_npos) return Status::Invalid("Undefined SessionOptionValue type "); switch ((SessionOptionValueType)(value.index())) { case SessionOptionValueType::kString: - opt.set_string_value(std::get(value)); + opt->set_string_value(std::get(value)); break; case SessionOptionValueType::kBool: - opt.set_bool_value(std::get(value)); + opt->set_bool_value(std::get(value)); break; case SessionOptionValueType::kInt32: - opt.set_int32_value(std::get(value)); + opt->set_int32_value(std::get(value)); break; case SessionOptionValueType::kInt64: - opt.set_int64_value(std::get(value)); + opt->set_int64_value(std::get(value)); break; case SessionOptionValueType::kFloat: - opt.set_float_value(std::get(value)); + opt->set_float_value(std::get(value)); break; case SessionOptionValueType::kDouble: - opt.set_double_value(std::get(value)); + opt->set_double_value(std::get(value)); break; case SessionOptionValueType::kStringList: - pb::sql::SessionOption::StringListValue& string_list_value = - *opt.mutable_string_list_value(); + pb::sql::SessionOption::StringListValue* string_list_value = + opt->mutable_string_list_value(); for (const std::string& s : std::get>(value)) - string_list_value.add_values(s); + string_list_value->add_values(s); break; } } From 7757c332cce37bf5a66913336ef5fdc9f93fd5d0 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 17 May 2023 16:03:46 -0700 Subject: [PATCH 004/195] Add partial (some gaps) ServerSessionMiddleware impl --- .../flight/sql/server_session_middleware.cc | 84 +++++++++++++++++++ .../flight/sql/server_session_middleware.h | 70 ++++++++++++++++ cpp/src/arrow/flight/sql/types.h | 6 +- 3 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 cpp/src/arrow/flight/sql/server_session_middleware.cc create mode 100644 cpp/src/arrow/flight/sql/server_session_middleware.h diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc new file mode 100644 index 0000000000000..f1896e85100de --- /dev/null +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -0,0 +1,84 @@ +// 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. + +#include "arrow/flight/sql/server_session_middleware.h" +#include +#include +#include +#include + +namespace arrow { +namespace flight { +namespace sql { + +ServerSessionMiddleware::ServerSessionMiddleware(ServerSessionMiddlewareFactory* factory, + const CallHeaders& headers) + : factory_(factory), headers_(headers), existing_session(false) {} +ServerSessionMiddleware::ServerSessionMiddleware( + ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, + std::shared_ptr> session) + : factory_(factory), headers_(headers), session_(session), existing_session(true) {} + +void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { + if (!existing_session && session_) { + // FIXME impl + // add Set-Cookie header w/ flight_sql_session_id + // FIXME I also need to know my own session key... + } +} +void ServerSessionMiddleware::CallCompleted(const Status&) {} +bool ServerSessionMiddleware::HasSession() { + return static_cast session_; +} +std::shared_ptr> +ServerSessionMiddleware::GetSession() { + if (session_) + return session_; + else { + auto new_session = factory_->GetNewSession(); + // FIXME + } +} +const CallHeaders& ServerSessionMiddleware::GetCallHeaders() { + return headers_; +} + +/// \brief FIXME +class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { + public: + Status StartCall(const CallInfo &info, const CallHeaders &incoming_headers, + std::shared_ptr *middleware) { + // FIXME impl + + } + std::pair>> + GetNewSession() { + // FIXME impl + } + private: + std::map>> session_store_; + boost::uuids::random_generator uuid_generator_; +}; + +std::shared_ptr MakeServerSessionMiddlewareFactory() { + return std::make_shared(); +} + +} // namespace sql +} // namespace flight +} // namespace arrow \ No newline at end of file diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h new file mode 100644 index 0000000000000..c8b76ed3fa93d --- /dev/null +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -0,0 +1,70 @@ +// 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. + +// (FIXME) + +#pragma once + +#include "arrow/flight/server_middleware.h" +#include "arrow/flight/sql/types.h" + +namespace arrow { +namespace flight { +namespace sql { + +class ServerSessionMiddlewareFactory; + +/// \brief FIXME +class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware + : public ServerMiddleware { + public: + ~ServerSessionMiddleware(); + + static constexpr char const kMiddlewareName[] = + "arrow::flight::ServerSessionMiddleware"; + + std::string name() const override { return kMiddlewareName; } + void SendingHeaders(AddCallHeaders*) override; + void CallCompleted(const Status&) override; + + bool HasSession(); + std::vector *GetSessionOptionsMap(); + const CallHeaders& GetCallHeaders(); + + private: + std::shared_ptr> session_; + const CallHeaders& headers_; + const bool existing_session; + ServerSessionMiddlewareFactory* factory_; + + + friend class ServerSessionMiddlewareFactory; + + explicit ServerSessionMiddleware(ServerSessionMiddlewareFactory*, + const CallHeaders& headers); + ServerSessionMiddleware(ServerSessionMiddlewareFactory*, + const CallHeaders&, + std::map*) +}; + +/// \brief Returns a ServerMiddlewareFactory that handles Session option storage. +ARROW_FLIGHT_SQL_EXPORT std::shared_ptr +MakeServerSessionMiddlewareFactory(); + +} // namespace sql +} // namespace flight +} // namespace arrow \ No newline at end of file diff --git a/cpp/src/arrow/flight/sql/types.h b/cpp/src/arrow/flight/sql/types.h index b216f47b6bbb4..900e29fe45767 100644 --- a/cpp/src/arrow/flight/sql/types.h +++ b/cpp/src/arrow/flight/sql/types.h @@ -44,7 +44,7 @@ using SqlInfoResult = /// \brief Map SQL info identifier to its value. using SqlInfoResultMap = std::unordered_map; -/// \brief Variant supporting all possible types for SetSessionOption +/// \brief Variant supporting all possible types for SetSessionOptions using SessionOptionValue = std::variant>; @@ -56,8 +56,8 @@ struct ARROW_FLIGHT_SQL_EXPORT SessionOption { std::string option_name; SessionOptionValue option_value; - SessionOption(std::string name, SessionOptionValue val) - : option_name{ name }, option_value{ val } {} + explicit SessionOption(std::string name, SessionOptionValue val) + : option_name{ std::move(name) }, option_value{ std::move(val) } {} SessionOption() {} }; From 4d7e4a04c98e1294cab8b7238abeac5c3a8730c9 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 14 Jun 2023 16:43:04 -0700 Subject: [PATCH 005/195] Initial StartCall impl, etc. --- .../flight/sql/server_session_middleware.cc | 110 +++++++++++++++--- .../flight/sql/server_session_middleware.h | 28 +++-- 2 files changed, 108 insertions(+), 30 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index f1896e85100de..6863fbf259271 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -25,9 +25,14 @@ namespace arrow { namespace flight { namespace sql { +// FIXME there isn't a sensible public client/server common header to move this to(?) +static constexpr char const kSessionCookieName[] = + "flight_sql_session_id"; + ServerSessionMiddleware::ServerSessionMiddleware(ServerSessionMiddlewareFactory* factory, const CallHeaders& headers) : factory_(factory), headers_(headers), existing_session(false) {} + ServerSessionMiddleware::ServerSessionMiddleware( ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, std::shared_ptr> session) @@ -37,42 +42,111 @@ void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { if (!existing_session && session_) { // FIXME impl // add Set-Cookie header w/ flight_sql_session_id - // FIXME I also need to know my own session key... + // FIXME I also need to know my own session key... (same fixme as header) } } void ServerSessionMiddleware::CallCompleted(const Status&) {} + bool ServerSessionMiddleware::HasSession() { return static_cast session_; } -std::shared_ptr> +std::shared_ptr>& ServerSessionMiddleware::GetSession() { - if (session_) - return session_; - else { - auto new_session = factory_->GetNewSession(); - // FIXME - } + if (!session_) + session_ = factory_->GetNewSession(&session_id_); + return session_; } const CallHeaders& ServerSessionMiddleware::GetCallHeaders() { return headers_; } -/// \brief FIXME +/// \brief A factory for ServerSessionMiddleware, itself storing session data. class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { + private: + std::map>> session_store_; + boost::uuids::random_generator uuid_generator_; + + std::vector> ParseCookieString( + const std::string_view& s) { + const std::string list_sep = "; "; + const std::string pair_sep = "="; + const size_t pair_sep_len = pair_sep.len(); + + std::vector> result; + + size_t cur = 0; + while (cur < s.length()) { + const size_t end = s.find(list_sep, cur); + size_t len; + if (end == std::string::npos) { + // No (further) list delimiters + len = str::string::npos; + cur = s.length(); + } else { + len = end - cur; + cur = end; + } + const std::string tok = s.substr(cur, len); + + const size_t val_pos = tok.find(pair_sep); + result.emplace_back( + /* FIXME (does this still need fixing?!) */ + tok.substr(0, val_pos), + tok.substr(val_pos + pair_sep_len, std::string::npos); + ); + } + + return result; + } + public: - Status StartCall(const CallInfo &info, const CallHeaders &incoming_headers, + Status StartCall(const CallInfo &, const CallHeaders &incoming_headers, std::shared_ptr *middleware) { - // FIXME impl + std::string session_id; + + const std::pair& + headers_it_pr = incoming_headers.equal_range("cookie"); + for (auto itr = headers_it_pr.first; itr != headers_it_pr.second, ++itr) { + const std::string_view& cookie_header = it->second; + const std::vector> cookies = + ParseCookieString(cookie_header); + for (const std::pair& cookie : cookies) { + if (cookie.first == kSessionCookieName) { + session_id = cookie.second; + if (!session_id.length()) + return Status::Invalid("Empty " + kSessionCookieName + " cookie value.") + } + } + if (session_id.length()) break; + } + + if (!session_id.length()) { + // No cookie was found + *middleware = std::make_shared(this, incoming_headers); + } else { + try { + auto session = session_store_.at(session_id); + *middleware = std::make_shared( + this, incoming_headers, session); + } catch (std::out_of_range& e) { + return Status::Invalid("Invalid or expired " + kSessionCookieName + " cookie.") + } + } + return Status::OK(); } - std::pair>> - GetNewSession() { - // FIXME impl + + /// \brief Get a new, empty session option map and its id key. + std::shared_ptr> + GetNewSession(std::shared_ptr* session_id) { + auto new_id = std::make_shared( + boost::lexical_cast(uuid_generator_())); + *session_id = new_id; + auto session = std::make_shared>() + session_store_[*new_id] = session; + return session; } - private: - std::map>> session_store_; - boost::uuids::random_generator uuid_generator_; }; std::shared_ptr MakeServerSessionMiddlewareFactory() { diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index c8b76ed3fa93d..223d5d7c12512 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -15,7 +15,8 @@ // specific language governing permissions and limitations // under the License. -// (FIXME) +// Middleware for handling Flight SQL Sessions including session cookie handling. +// Currently experimental. #pragma once @@ -28,37 +29,40 @@ namespace sql { class ServerSessionMiddlewareFactory; -/// \brief FIXME +// FIXME put the cookie name somewhere static out here + +/// \brief A middleware to handle Session option persistence and related *Cookie headers. class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware { public: - ~ServerSessionMiddleware(); - static constexpr char const kMiddlewareName[] = - "arrow::flight::ServerSessionMiddleware"; + "arrow::flight::sql::ServerSessionMiddleware"; std::string name() const override { return kMiddlewareName; } void SendingHeaders(AddCallHeaders*) override; void CallCompleted(const Status&) override; - bool HasSession(); - std::vector *GetSessionOptionsMap(); - const CallHeaders& GetCallHeaders(); + /// \brief Is there an existing session (either existing or new) + bool HasSession() const; + /// \brief Get a mutable Map of session options. + std::shared_ptr> GetSessionOptionsMap(const std::string&); + /// \brief Get request headers, in lieu of a provided or created session. + const CallHeaders& GetCallHeaders() const; private: + friend class ServerSessionMiddlewareFactory; std::shared_ptr> session_; + // For use when existing_session is false but a session has been established. + std::shared_ptr session_id_; const CallHeaders& headers_; const bool existing_session; ServerSessionMiddlewareFactory* factory_; - - friend class ServerSessionMiddlewareFactory; - explicit ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders& headers); ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders&, - std::map*) + std::shared_ptr>) }; /// \brief Returns a ServerMiddlewareFactory that handles Session option storage. From a6d28995980e999ee83862bb5208f05fa95f254b Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 16 Jun 2023 14:19:12 -0700 Subject: [PATCH 006/195] Prelim impl ServerSessionMWFactory locking --- .../flight/sql/server_session_middleware.cc | 21 ++++++++++++------- .../flight/sql/server_session_middleware.h | 8 +++---- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 6863fbf259271..a5ac35a84972f 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. +#include #include "arrow/flight/sql/server_session_middleware.h" #include #include @@ -35,7 +36,8 @@ ServerSessionMiddleware::ServerSessionMiddleware(ServerSessionMiddlewareFactory* ServerSessionMiddleware::ServerSessionMiddleware( ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, - std::shared_ptr> session) + std::shared_ptr> session, + std::string session_id) : factory_(factory), headers_(headers), session_(session), existing_session(true) {} void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { @@ -65,6 +67,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { private: std::map>> session_store_; + std::share_mutex session_store_lock_; boost::uuids::random_generator uuid_generator_; std::vector> ParseCookieString( @@ -91,7 +94,6 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { const size_t val_pos = tok.find(pair_sep); result.emplace_back( - /* FIXME (does this still need fixing?!) */ tok.substr(0, val_pos), tok.substr(val_pos + pair_sep_len, std::string::npos); ); @@ -126,9 +128,10 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { *middleware = std::make_shared(this, incoming_headers); } else { try { + const std::shared_lock l(session_store_lock_); auto session = session_store_.at(session_id); *middleware = std::make_shared( - this, incoming_headers, session); + this, incoming_headers, session, session_id); } catch (std::out_of_range& e) { return Status::Invalid("Invalid or expired " + kSessionCookieName + " cookie.") } @@ -139,12 +142,14 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { /// \brief Get a new, empty session option map and its id key. std::shared_ptr> - GetNewSession(std::shared_ptr* session_id) { - auto new_id = std::make_shared( - boost::lexical_cast(uuid_generator_())); + GetNewSession(std::string* session_id) { + std::string new_id = boost::lexical_cast(uuid_generator_()); *session_id = new_id; - auto session = std::make_shared>() - session_store_[*new_id] = session; + auto session = std::make_shared>(); + + const std::unique_lock l(session_store_lock_); + session_store_[new_id] = session; + return session; } }; diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 223d5d7c12512..2001de271d7a6 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -45,15 +45,14 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware /// \brief Is there an existing session (either existing or new) bool HasSession() const; /// \brief Get a mutable Map of session options. - std::shared_ptr> GetSessionOptionsMap(const std::string&); + std::shared_ptr> GetSession(std::string*); /// \brief Get request headers, in lieu of a provided or created session. const CallHeaders& GetCallHeaders() const; private: friend class ServerSessionMiddlewareFactory; std::shared_ptr> session_; - // For use when existing_session is false but a session has been established. - std::shared_ptr session_id_; + std::string session_id_; const CallHeaders& headers_; const bool existing_session; ServerSessionMiddlewareFactory* factory_; @@ -62,7 +61,8 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware const CallHeaders& headers); ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders&, - std::shared_ptr>) + std::shared_ptr>, + std::string) }; /// \brief Returns a ServerMiddlewareFactory that handles Session option storage. From 360f23beae81b4bdeec4ec11113946786d7cde83 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 22 Jun 2023 10:08:08 -0700 Subject: [PATCH 007/195] Untested initial middleware impl --- .../flight/sql/server_session_middleware.cc | 49 ++++++++++++------- .../flight/sql/server_session_middleware.h | 32 ++++++++---- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index a5ac35a84972f..77771063bf45e 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -26,33 +26,28 @@ namespace arrow { namespace flight { namespace sql { -// FIXME there isn't a sensible public client/server common header to move this to(?) -static constexpr char const kSessionCookieName[] = - "flight_sql_session_id"; - ServerSessionMiddleware::ServerSessionMiddleware(ServerSessionMiddlewareFactory* factory, const CallHeaders& headers) : factory_(factory), headers_(headers), existing_session(false) {} ServerSessionMiddleware::ServerSessionMiddleware( ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, - std::shared_ptr> session, + std::shared_ptr session, std::string session_id) : factory_(factory), headers_(headers), session_(session), existing_session(true) {} void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { if (!existing_session && session_) { - // FIXME impl - // add Set-Cookie header w/ flight_sql_session_id - // FIXME I also need to know my own session key... (same fixme as header) + addCallHeaders->AddHeader("cookie", kSessionCookieName + "=" + session_id_;); } } + void ServerSessionMiddleware::CallCompleted(const Status&) {} bool ServerSessionMiddleware::HasSession() { - return static_cast session_; + return static_cast(session_); } -std::shared_ptr>& +std::shared_ptr& ServerSessionMiddleware::GetSession() { if (!session_) session_ = factory_->GetNewSession(&session_id_); @@ -64,10 +59,9 @@ const CallHeaders& ServerSessionMiddleware::GetCallHeaders() { /// \brief A factory for ServerSessionMiddleware, itself storing session data. class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { - private: - std::map>> session_store_; - std::share_mutex session_store_lock_; + protected: + std::map> session_store_; + std::shared_mutex session_store_lock_; boost::uuids::random_generator uuid_generator_; std::vector> ParseCookieString( @@ -141,15 +135,15 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { } /// \brief Get a new, empty session option map and its id key. - std::shared_ptr> + std::shared_ptr GetNewSession(std::string* session_id) { std::string new_id = boost::lexical_cast(uuid_generator_()); *session_id = new_id; - auto session = std::make_shared>(); + auto session = std::make_shared(); const std::unique_lock l(session_store_lock_); session_store_[new_id] = session; - + return session; } }; @@ -158,6 +152,27 @@ std::shared_ptr MakeServerSessionMiddlewareFactory() { return std::make_shared(); } +class FlightSqlSession { + protected: + std::map map_; + std::shared_mutex lock_; + public: + /// \brief Get session option by key + SessionOptionValue GetSessionOption(const std::string& k) const { + const std::shared_lock l(lock_); + return map_.at(k); + } + void SetSessionOption(const std::string& k, const SessionOptionValue& v) { + const std::unique_lock l(lock_): + map_[k] = v; + } + /// \brief Idempotently remove key from this call's Session, if Session & key exist + void EraseSessionOption(const std::string& k) { + const std::unique_lock l(lock_); + map_.erase(k); + } +}; + } // namespace sql } // namespace flight } // namespace arrow \ No newline at end of file diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 2001de271d7a6..2175a71fa963c 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -29,7 +29,21 @@ namespace sql { class ServerSessionMiddlewareFactory; -// FIXME put the cookie name somewhere static out here +static constexpr char const kSessionCookieName[] = + "flight_sql_session_id"; + +class FlightSqlSession { + protected: + std::map map_; + std::shared_mutex lock_; + public: + /// \brief Get session option by key + SessionOptionValue GetSessionOption(const std::string&) const; + /// \brief Set session option by key to given value + void SetSessionOption(const std::string&, const SessionOptionValue&); + /// \brief Idempotently remove key from this call's Session, if Session & key exist + void EraseSessionOption(const std::string&); +}; /// \brief A middleware to handle Session option persistence and related *Cookie headers. class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware @@ -44,25 +58,25 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware /// \brief Is there an existing session (either existing or new) bool HasSession() const; - /// \brief Get a mutable Map of session options. - std::shared_ptr> GetSession(std::string*); + /// \brief Get existing or new call-associated session + std::shared_ptr GetSession(); /// \brief Get request headers, in lieu of a provided or created session. const CallHeaders& GetCallHeaders() const; - private: + protected: friend class ServerSessionMiddlewareFactory; - std::shared_ptr> session_; + std::shared_ptr session_; std::string session_id_; const CallHeaders& headers_; const bool existing_session; ServerSessionMiddlewareFactory* factory_; - explicit ServerSessionMiddleware(ServerSessionMiddlewareFactory*, - const CallHeaders& headers); + ServerSessionMiddleware(ServerSessionMiddlewareFactory*, + const CallHeaders&); ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders&, - std::shared_ptr>, - std::string) + std::shared_ptr, + std::string session_id) }; /// \brief Returns a ServerMiddlewareFactory that handles Session option storage. From 672a26674dcdd09523bf34061bdd1c67ad579bef Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 23 Jun 2023 11:00:44 -0700 Subject: [PATCH 008/195] Rename lock_ and remove duplicitous comments --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 77771063bf45e..fc912a0c8ba66 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -155,20 +155,18 @@ std::shared_ptr MakeServerSessionMiddlewareFactory() { class FlightSqlSession { protected: std::map map_; - std::shared_mutex lock_; + std::shared_mutex map_lock_; public: - /// \brief Get session option by key SessionOptionValue GetSessionOption(const std::string& k) const { - const std::shared_lock l(lock_); + const std::shared_lock l(map_lock_); return map_.at(k); } void SetSessionOption(const std::string& k, const SessionOptionValue& v) { - const std::unique_lock l(lock_): + const std::unique_lock l(map_lock_): map_[k] = v; } - /// \brief Idempotently remove key from this call's Session, if Session & key exist void EraseSessionOption(const std::string& k) { - const std::unique_lock l(lock_); + const std::unique_lock l(map_lock_); map_.erase(k); } }; From 9194302b95357a8d5196a9d37be2e6d27d95a10e Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 23 Jun 2023 12:19:02 -0700 Subject: [PATCH 009/195] Make code build --- cpp/src/arrow/flight/sql/CMakeLists.txt | 3 +- .../flight/sql/server_session_middleware.cc | 133 +++++++++--------- .../flight/sql/server_session_middleware.h | 10 +- 3 files changed, 75 insertions(+), 71 deletions(-) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index b0a551a2bca77..6c31db10b204b 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -47,7 +47,8 @@ set(ARROW_FLIGHT_SQL_SRCS sql_info_internal.cc column_metadata.cc client.cc - protocol_internal.cc) + protocol_internal.cc + server_session_middleware.cc) add_arrow_lib(arrow_flight_sql CMAKE_PACKAGE_NAME diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index fc912a0c8ba66..0c0067c39a054 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -26,37 +26,6 @@ namespace arrow { namespace flight { namespace sql { -ServerSessionMiddleware::ServerSessionMiddleware(ServerSessionMiddlewareFactory* factory, - const CallHeaders& headers) - : factory_(factory), headers_(headers), existing_session(false) {} - -ServerSessionMiddleware::ServerSessionMiddleware( - ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, - std::shared_ptr session, - std::string session_id) - : factory_(factory), headers_(headers), session_(session), existing_session(true) {} - -void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { - if (!existing_session && session_) { - addCallHeaders->AddHeader("cookie", kSessionCookieName + "=" + session_id_;); - } -} - -void ServerSessionMiddleware::CallCompleted(const Status&) {} - -bool ServerSessionMiddleware::HasSession() { - return static_cast(session_); -} -std::shared_ptr& -ServerSessionMiddleware::GetSession() { - if (!session_) - session_ = factory_->GetNewSession(&session_id_); - return session_; -} -const CallHeaders& ServerSessionMiddleware::GetCallHeaders() { - return headers_; -} - /// \brief A factory for ServerSessionMiddleware, itself storing session data. class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { protected: @@ -68,9 +37,9 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { const std::string_view& s) { const std::string list_sep = "; "; const std::string pair_sep = "="; - const size_t pair_sep_len = pair_sep.len(); + const size_t pair_sep_len = pair_sep.length(); - std::vector> result; + std::vector> result; size_t cur = 0; while (cur < s.length()) { @@ -78,18 +47,18 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { size_t len; if (end == std::string::npos) { // No (further) list delimiters - len = str::string::npos; + len = std::string::npos; cur = s.length(); } else { len = end - cur; cur = end; } - const std::string tok = s.substr(cur, len); + const std::string_view tok = s.substr(cur, len); const size_t val_pos = tok.find(pair_sep); result.emplace_back( - tok.substr(0, val_pos), - tok.substr(val_pos + pair_sep_len, std::string::npos); + tok.substr(0, val_pos), + tok.substr(val_pos + pair_sep_len, std::string::npos) ); } @@ -103,15 +72,17 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { const std::pair& headers_it_pr = incoming_headers.equal_range("cookie"); - for (auto itr = headers_it_pr.first; itr != headers_it_pr.second, ++itr) { - const std::string_view& cookie_header = it->second; + for (auto itr = headers_it_pr.first; itr != headers_it_pr.second; ++itr) { + const std::string_view& cookie_header = itr->second; const std::vector> cookies = ParseCookieString(cookie_header); for (const std::pair& cookie : cookies) { if (cookie.first == kSessionCookieName) { session_id = cookie.second; if (!session_id.length()) - return Status::Invalid("Empty " + kSessionCookieName + " cookie value.") + return Status::Invalid( + "Empty " + static_cast(kSessionCookieName) + + " cookie value."); } } if (session_id.length()) break; @@ -119,15 +90,19 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { if (!session_id.length()) { // No cookie was found - *middleware = std::make_shared(this, incoming_headers); + *middleware = std::shared_ptr( + new ServerSessionMiddleware(this, incoming_headers)); } else { try { const std::shared_lock l(session_store_lock_); auto session = session_store_.at(session_id); - *middleware = std::make_shared( - this, incoming_headers, session, session_id); + *middleware = std::shared_ptr( + new ServerSessionMiddleware(this, incoming_headers, + session, session_id)); } catch (std::out_of_range& e) { - return Status::Invalid("Invalid or expired " + kSessionCookieName + " cookie.") + return Status::Invalid( + "Invalid or expired " + + static_cast(kSessionCookieName) + " cookie."); } } @@ -135,8 +110,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { } /// \brief Get a new, empty session option map and its id key. - std::shared_ptr - GetNewSession(std::string* session_id) { + std::shared_ptr GetNewSession(std::string* session_id) { std::string new_id = boost::lexical_cast(uuid_generator_()); *session_id = new_id; auto session = std::make_shared(); @@ -148,28 +122,57 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { } }; +ServerSessionMiddleware::ServerSessionMiddleware(ServerSessionMiddlewareFactory* factory, + const CallHeaders& headers) + : factory_(factory), headers_(headers), existing_session(false) {} + +ServerSessionMiddleware::ServerSessionMiddleware( + ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, + std::shared_ptr session, + std::string session_id) + : factory_(factory), headers_(headers), session_(session), existing_session(true) {} + +void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { + if (!existing_session && session_) { + addCallHeaders->AddHeader( + "cookie", + static_cast(kSessionCookieName) + "=" + session_id_); + } +} + +void ServerSessionMiddleware::CallCompleted(const Status&) {} + +bool ServerSessionMiddleware::HasSession() const { + return static_cast(session_); +} +std::shared_ptr ServerSessionMiddleware::GetSession() { + if (!session_) + session_ = factory_->GetNewSession(&session_id_); + return session_; +} +const CallHeaders& ServerSessionMiddleware::GetCallHeaders() const { + return headers_; +} + + + std::shared_ptr MakeServerSessionMiddlewareFactory() { - return std::make_shared(); + return std::shared_ptr( + new ServerSessionMiddlewareFactory()); } -class FlightSqlSession { - protected: - std::map map_; - std::shared_mutex map_lock_; - public: - SessionOptionValue GetSessionOption(const std::string& k) const { - const std::shared_lock l(map_lock_); - return map_.at(k); - } - void SetSessionOption(const std::string& k, const SessionOptionValue& v) { - const std::unique_lock l(map_lock_): - map_[k] = v; - } - void EraseSessionOption(const std::string& k) { - const std::unique_lock l(map_lock_); - map_.erase(k); - } -}; +SessionOptionValue FlightSqlSession::GetSessionOption(const std::string& k) { + const std::shared_lock l(map_lock_); + return map_.at(k); +} +void FlightSqlSession::SetSessionOption(const std::string& k, const SessionOptionValue& v) { + const std::unique_lock l(map_lock_); + map_[k] = v; +} +void FlightSqlSession::EraseSessionOption(const std::string& k) { + const std::unique_lock l(map_lock_); + map_.erase(k); +} } // namespace sql } // namespace flight diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 2175a71fa963c..ca44e36ace910 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -35,10 +35,10 @@ static constexpr char const kSessionCookieName[] = class FlightSqlSession { protected: std::map map_; - std::shared_mutex lock_; + std::shared_mutex map_lock_; public: /// \brief Get session option by key - SessionOptionValue GetSessionOption(const std::string&) const; + SessionOptionValue GetSessionOption(const std::string&); /// \brief Set session option by key to given value void SetSessionOption(const std::string&, const SessionOptionValue&); /// \brief Idempotently remove key from this call's Session, if Session & key exist @@ -65,18 +65,18 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware protected: friend class ServerSessionMiddlewareFactory; + ServerSessionMiddlewareFactory* factory_; + const CallHeaders& headers_; std::shared_ptr session_; std::string session_id_; - const CallHeaders& headers_; const bool existing_session; - ServerSessionMiddlewareFactory* factory_; ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders&); ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders&, std::shared_ptr, - std::string session_id) + std::string session_id); }; /// \brief Returns a ServerMiddlewareFactory that handles Session option storage. From 888ff22c10c816682767b70bbeb1a12cef707254 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 23 Jun 2023 15:30:15 -0700 Subject: [PATCH 010/195] Fix server set-cookie header name --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 0c0067c39a054..4e80cad3e8db6 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -135,7 +135,7 @@ ServerSessionMiddleware::ServerSessionMiddleware( void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { if (!existing_session && session_) { addCallHeaders->AddHeader( - "cookie", + "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); } } From 3326ad8b04201a2590c25de405ca420349f1fc3d Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 27 Jun 2023 18:37:30 -0700 Subject: [PATCH 011/195] Remove/revert abandoned Location changes --- cpp/src/arrow/flight/types.cc | 28 ---------------------------- cpp/src/arrow/flight/types.h | 9 --------- 2 files changed, 37 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 1f65b24595b26..1d43c41b69d9f 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -516,34 +516,6 @@ std::string Location::scheme() const { return scheme; } -std::string Location::path() const { return uri_->path(); } -arrow::Result>> Location::QueryItems() - const { - return uri_->query_items(); -} - -arrow::Result>> Location::AsHeaders() - const { - std::string catalog = path(); - if (catalog.empty()) { - return QueryItems(); - } - - std::vector> headers; - - auto query_items_result = QueryItems(); - if (!query_items_result.ok()) { - return query_items_result; - } - std::vector> items(*query_items_result); - headers.reserve(items.size() + 1); - - headers.emplace_back(std::pair("catalog", catalog)); - headers.insert(headers.end(), items.begin(), items.end()); - - return headers; -} - bool Location::Equals(const Location& other) const { return ToString() == other.ToString(); } diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index c5299d25882b0..790a2067dd705 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -450,15 +450,6 @@ struct ARROW_FLIGHT_EXPORT Location { /// \brief Get the scheme of this URI. std::string scheme() const; - /// \brief Get the path of this URI. - std::string path() const; - - /// \brief Get the query parameters of this URI. - arrow::Result>> QueryItems() const; - - /// \brief Convert URI path and parameters to headers. - arrow::Result>> AsHeaders() const; - bool Equals(const Location& other) const; friend bool operator==(const Location& left, const Location& right) { From 6041b2867dd4be44fa9f0be81cc0d665f8ee87c1 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 13 Jul 2023 16:53:18 -0700 Subject: [PATCH 012/195] [BUILDS] Move Session messages to Flight PB --- cpp/src/arrow/flight/sql/client.cc | 51 +++++------ cpp/src/arrow/flight/sql/protocol_internal.h | 1 + cpp/src/arrow/flight/sql/server.cc | 50 +++++------ format/Flight.proto | 92 ++++++++++++++++++++ format/FlightSql.proto | 88 ------------------- 5 files changed, 144 insertions(+), 138 deletions(-) diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index 6dd2bc58341ad..8fc2fd12480f9 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -31,6 +31,7 @@ #include "arrow/result.h" #include "arrow/util/logging.h" +namespace pb = arrow::flight::protocol; namespace flight_sql_pb = arrow::flight::protocol::sql; namespace arrow { @@ -800,9 +801,9 @@ ::arrow::Result FlightSqlClient::CancelQuery( ::arrow::Result> FlightSqlClient::SetSessionOptions( const FlightCallOptions& options, const std::vector& session_options) { - flight_sql_pb::ActionSetSessionOptionsRequest request; + pb::ActionSetSessionOptionsRequest request; for (const SessionOption& in_opt : session_options) { - flight_sql_pb::SessionOption* opt = request.add_session_options(); + pb::SessionOption* opt = request.add_session_options(); const std::string& name = in_opt.option_name; opt->set_option_name(name); @@ -829,7 +830,7 @@ ::arrow::Result> FlightSqlClient::SetSession opt->set_double_value(std::get(value)); break; case SessionOptionValueType::kStringList: - flight_sql_pb::SessionOption::StringListValue* string_list_value = + pb::SessionOption::StringListValue* string_list_value = opt->mutable_string_list_value(); for (const std::string& s : std::get>(value)) string_list_value->add_values(s); @@ -841,24 +842,24 @@ ::arrow::Result> FlightSqlClient::SetSession ARROW_ASSIGN_OR_RAISE(auto action, PackAction("SetSessionOptions", request)); ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); - flight_sql_pb::ActionSetSessionOptionsResult pb_result; + pb::ActionSetSessionOptionsResult pb_result; ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); std::vector result; for (const int result_value : pb_result.results()) { switch (result_value) { - case flight_sql_pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED: + case pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED: result.push_back(SetSessionOptionResult::kUnspecified); break; - case flight_sql_pb::ActionSetSessionOptionsResult + case pb::ActionSetSessionOptionsResult ::SET_SESSION_OPTION_RESULT_OK: result.push_back(SetSessionOptionResult::kOk); break; - case flight_sql_pb::ActionSetSessionOptionsResult + case pb::ActionSetSessionOptionsResult ::SET_SESSION_OPTION_RESULT_INVALID_VALUE: result.push_back(SetSessionOptionResult::kInvalidResult); break; - case flight_sql_pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR: + case pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR: result.push_back(SetSessionOptionResult::kError); break; } @@ -869,44 +870,44 @@ ::arrow::Result> FlightSqlClient::SetSession ::arrow::Result> FlightSqlClient::GetSessionOptions ( const FlightCallOptions& options) { - flight_sql_pb::ActionGetSessionOptionsRequest request; + pb::ActionGetSessionOptionsRequest request; std::unique_ptr results; ARROW_ASSIGN_OR_RAISE(auto action, PackAction("GetSessionOptions", request)); ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); - flight_sql_pb::ActionGetSessionOptionsResult pb_result; + pb::ActionGetSessionOptionsResult pb_result; ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); std::vector result; if (pb_result.session_options_size() > 0) { result.reserve(pb_result.session_options_size()); - for (const flight_sql_pb::SessionOption& in_opt : pb_result.session_options()) { + for (const pb::SessionOption& in_opt : pb_result.session_options()) { const std::string& name = in_opt.option_name(); SessionOptionValue val; switch (in_opt.option_value_case()) { - case flight_sql_pb::SessionOption::OPTION_VALUE_NOT_SET: + case pb::SessionOption::OPTION_VALUE_NOT_SET: return Status::Invalid("Unset option_value for name '" + name + "'"); - case flight_sql_pb::SessionOption::kStringValue: + case pb::SessionOption::kStringValue: val = in_opt.string_value(); break; - case flight_sql_pb::SessionOption::kBoolValue: + case pb::SessionOption::kBoolValue: val = in_opt.bool_value(); break; - case flight_sql_pb::SessionOption::kInt32Value: + case pb::SessionOption::kInt32Value: val = in_opt.int32_value(); break; - case flight_sql_pb::SessionOption::kInt64Value: + case pb::SessionOption::kInt64Value: val = in_opt.int64_value(); break; - case flight_sql_pb::SessionOption::kFloatValue: + case pb::SessionOption::kFloatValue: val = in_opt.float_value(); break; - case flight_sql_pb::SessionOption::kDoubleValue: + case pb::SessionOption::kDoubleValue: val = in_opt.double_value(); break; - case flight_sql_pb::SessionOption::kStringListValue: + case pb::SessionOption::kStringListValue: val.emplace>(); std::get>(val) .reserve(in_opt.string_list_value().values_size()); @@ -923,23 +924,23 @@ ::arrow::Result> FlightSqlClient::GetSessionOptions ( ::arrow::Result FlightSqlClient::CloseSession( const FlightCallOptions& options) { - flight_sql_pb::ActionCloseSessionRequest request; + pb::ActionCloseSessionRequest request; std::unique_ptr results; ARROW_ASSIGN_OR_RAISE(auto action, PackAction("CloseSession", request)); ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); - flight_sql_pb::ActionCloseSessionResult result; + pb::ActionCloseSessionResult result; ARROW_RETURN_NOT_OK(ReadResult(results.get(), &result)); ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); switch (result.result()) { - case flight_sql_pb::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED: + case pb::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED: return CloseSessionResult::kUnspecified; - case flight_sql_pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSED: + case pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSED: return CloseSessionResult::kClosed; - case flight_sql_pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSING: + case pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSING: return CloseSessionResult::kClosing; - case flight_sql_pb::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE: + case pb::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE: return CloseSessionResult::kNotClosable; default: break; diff --git a/cpp/src/arrow/flight/sql/protocol_internal.h b/cpp/src/arrow/flight/sql/protocol_internal.h index ce50ad2f61b1e..71e82eb83bb4f 100644 --- a/cpp/src/arrow/flight/sql/protocol_internal.h +++ b/cpp/src/arrow/flight/sql/protocol_internal.h @@ -24,3 +24,4 @@ #include "arrow/flight/sql/visibility.h" #include "arrow/flight/sql/FlightSql.pb.h" // IWYU pragma: export +#include "arrow/flight/Flight.pb.h" diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index 8176a6d4f87c2..15ecccc01fbc5 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -272,7 +272,7 @@ arrow::Result ParseActionCancelQueryRequest( arrow::Result ParseActionCloseSessionRequest( const google::protobuf::Any& any) { - pb::sql::ActionCloseSessionRequest command; + pb::ActionCloseSessionRequest command; if (!any.UnpackTo(&command)) { return Status::Invalid("Unable to unpack ActionCloseSessionRequest"); } @@ -373,7 +373,7 @@ arrow::Result ParseActionEndTransactionRequest( arrow::Result ParseActionSetSessionOptionsRequest( const google::protobuf::Any& any) { - pb::sql::ActionSetSessionOptionsRequest command; + pb::ActionSetSessionOptionsRequest command; if (!any.UnpackTo(&command)) { return Status::Invalid("Unable to unpack ActionSetSessionOptionsRequest"); } @@ -381,31 +381,31 @@ arrow::Result ParseActionSetSessionOptionsReques ActionSetSessionOptionsRequest result; if (command.session_options_size() > 0) { result.session_options.reserve(command.session_options_size()); - for (const pb::sql::SessionOption& in_opt : command.session_options()) { + for (const pb::SessionOption& in_opt : command.session_options()) { const std::string& name = in_opt.option_name(); SessionOptionValue val; switch (in_opt.option_value_case()) { - case pb::sql::SessionOption::OPTION_VALUE_NOT_SET: + case pb::SessionOption::OPTION_VALUE_NOT_SET: return Status::Invalid("Unset SessionOptionValue for name '" + name + "'"); - case pb::sql::SessionOption::kStringValue: + case pb::SessionOption::kStringValue: val = in_opt.string_value(); break; - case pb::sql::SessionOption::kBoolValue: + case pb::SessionOption::kBoolValue: val = in_opt.bool_value(); break; - case pb::sql::SessionOption::kInt32Value: + case pb::SessionOption::kInt32Value: val = in_opt.int32_value(); break; - case pb::sql::SessionOption::kInt64Value: + case pb::SessionOption::kInt64Value: val = in_opt.int64_value(); break; - case pb::sql::SessionOption::kFloatValue: + case pb::SessionOption::kFloatValue: val = in_opt.float_value(); break; - case pb::sql::SessionOption::kDoubleValue: + case pb::SessionOption::kDoubleValue: val = in_opt.double_value(); break; - case pb::sql::SessionOption::kStringListValue: + case pb::SessionOption::kStringListValue: val.emplace>(); std::get>(val) .reserve(in_opt.string_list_value().values_size()); @@ -422,7 +422,7 @@ arrow::Result ParseActionSetSessionOptionsReques arrow::Result ParseActionGetSessionOptionsRequest( const google::protobuf::Any& any) { - pb::sql::ActionGetSessionOptionsRequest command; + pb::ActionGetSessionOptionsRequest command; if (!any.UnpackTo(&command)) { return Status::Invalid("Unable to unpack ActionGetSessionOptionsRequest"); } @@ -514,24 +514,24 @@ arrow::Result PackActionResult(ActionCreatePreparedStatementResult resul } arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { - pb::sql::ActionSetSessionOptionsResult pb_result; + pb::ActionSetSessionOptionsResult pb_result; for (const SetSessionOptionResult res : result.results) { switch (res) { case SetSessionOptionResult::kUnspecified: pb_result.add_results( - pb::sql::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED); + pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED); break; case SetSessionOptionResult::kOk: pb_result.add_results( - pb::sql::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_OK); + pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_OK); break; case SetSessionOptionResult::kInvalidResult: pb_result.add_results( - pb::sql::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_INVALID_VALUE); + pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_INVALID_VALUE); break; case SetSessionOptionResult::kError: pb_result.add_results( - pb::sql::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR); + pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR); break; } } @@ -539,9 +539,9 @@ arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { } arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { - pb::sql::ActionGetSessionOptionsResult pb_result; + pb::ActionGetSessionOptionsResult pb_result; for (const SessionOption& in_opt : result.session_options) { - pb::sql::SessionOption* opt = pb_result.add_session_options(); + pb::SessionOption* opt = pb_result.add_session_options(); const std::string& name = in_opt.option_name; opt->set_option_name(name); @@ -568,7 +568,7 @@ arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { opt->set_double_value(std::get(value)); break; case SessionOptionValueType::kStringList: - pb::sql::SessionOption::StringListValue* string_list_value = + pb::SessionOption::StringListValue* string_list_value = opt->mutable_string_list_value(); for (const std::string& s : std::get>(value)) string_list_value->add_values(s); @@ -580,19 +580,19 @@ arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { } arrow::Result PackActionResult(CloseSessionResult result) { - pb::sql::ActionCloseSessionResult pb_result; + pb::ActionCloseSessionResult pb_result; switch (result) { case CloseSessionResult::kUnspecified: - pb_result.set_result(pb::sql::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED); + pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED); break; case CloseSessionResult::kClosed: - pb_result.set_result(pb::sql::ActionCloseSessionResult::CLOSE_RESULT_CLOSED); + pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSED); break; case CloseSessionResult::kClosing: - pb_result.set_result(pb::sql::ActionCloseSessionResult::CLOSE_RESULT_CLOSING); + pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSING); break; case CloseSessionResult::kNotClosable: - pb_result.set_result(pb::sql::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE); + pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE); break; } return PackActionResult(pb_result); diff --git a/format/Flight.proto b/format/Flight.proto index de3794f05ba83..86db2f42255be 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -525,3 +525,95 @@ message FlightData { message PutResult { bytes app_metadata = 1; } + +/* + * Request message for the "Close Session" action. + */ +message ActionCloseSessionRequest { + option (experimental) = true; +} + +/* + * The result of closing a session. + * + * The result should be wrapped in a google.protobuf.Any message. + */ +message ActionCloseSessionResult { + option (experimental) = true; + + enum CloseSessionResult { + // The session close status is unknown. Servers should avoid using + // this value (send a NOT_FOUND error if the requested query is + // not known). Clients can retry the request. + CLOSE_RESULT_UNSPECIFIED = 0; + // The session close request is complete. Subsequent requests with + // a NOT_FOUND error. + CLOSE_RESULT_CLOSED = 1; + // The session close request is in progress. The client may retry + // the close request. + CLOSE_RESULT_CLOSING = 2; + // The session is not closeable. The client should not retry the + // close request. + CLOSE_RESULT_NOT_CLOSEABLE = 3; + } + + CloseSessionResult result = 1; +} + +message SessionOption { + option (experimental) = true; + + message StringListValue { + repeated string values = 1; + } + + string option_name = 1; + oneof option_value { + string string_value = 2; + bool bool_value = 3; + sfixed32 int32_value = 4; + sfixed64 int64_value = 5; + float float_value = 6; + double double_value = 7; + StringListValue string_list_value = 8; + } +} + +message ActionSetSessionOptionsRequest { + option (experimental) = true; + + repeated SessionOption session_options = 1; +} + +message ActionSetSessionOptionsResult { + option (experimental) = true; + + enum SetSessionOptionResult { + // The status of setting the option is unknown. Servers should avoid using + // this value (send a NOT_FOUND error if the requested query is + // not known). Clients can retry the request. + SET_SESSION_OPTION_RESULT_UNSPECIFIED = 0; + // The session option setting completed successfully. + SET_SESSION_OPTION_RESULT_OK = 1; + // The session cannot be set to the given value. + SET_SESSION_OPTION_RESULT_INVALID_VALUE = 2; + // The session cannot be set. + SET_SESSION_OPTION_RESULT_ERROR = 3; + } + + repeated SetSessionOptionResult results = 1; +} + +message ActionGetSessionOptionsRequest { + option (experimental) = true; +} + +message ActionGetSessionOptionsResult { + option (experimental) = true; + + repeated SessionOption session_options = 1; +} + +extend google.protobuf.MessageOptions { + bool experimental = 1000; +} diff --git a/format/FlightSql.proto b/format/FlightSql.proto index 840a22eff9983..581cf1f76d57c 100644 --- a/format/FlightSql.proto +++ b/format/FlightSql.proto @@ -1856,94 +1856,6 @@ message ActionCancelQueryResult { CancelResult result = 1; } -/* - * Request message for the "Close Session" action. - */ -message ActionCloseSessionRequest { - option (experimental) = true; -} - -/* - * The result of closing a session. - * - * The result should be wrapped in a google.protobuf.Any message. - */ -message ActionCloseSessionResult { - option (experimental) = true; - - enum CloseSessionResult { - // The session close status is unknown. Servers should avoid using - // this value (send a NOT_FOUND error if the requested query is - // not known). Clients can retry the request. - CLOSE_RESULT_UNSPECIFIED = 0; - // The session close request is complete. Subsequent requests with - // a NOT_FOUND error. - CLOSE_RESULT_CLOSED = 1; - // The session close request is in progress. The client may retry - // the close request. - CLOSE_RESULT_CLOSING = 2; - // The session is not closeable. The client should not retry the - // close request. - CLOSE_RESULT_NOT_CLOSEABLE = 3; - } - - CloseSessionResult result = 1; -} - -message SessionOption { - option (experimental) = true; - - message StringListValue { - repeated string values = 1; - } - - string option_name = 1; - oneof option_value { - string string_value = 2; - bool bool_value = 3; - sfixed32 int32_value = 4; - sfixed64 int64_value = 5; - float float_value = 6; - double double_value = 7; - StringListValue string_list_value = 8; - } -} - -message ActionSetSessionOptionsRequest { - option (experimental) = true; - - repeated SessionOption session_options = 1; -} - -message ActionSetSessionOptionsResult { - option (experimental) = true; - - enum SetSessionOptionResult { - // The status of setting the option is unknown. Servers should avoid using - // this value (send a NOT_FOUND error if the requested query is - // not known). Clients can retry the request. - SET_SESSION_OPTION_RESULT_UNSPECIFIED = 0; - // The session option setting completed successfully. - SET_SESSION_OPTION_RESULT_OK = 1; - // The session cannot be set to the given value. - SET_SESSION_OPTION_RESULT_INVALID_VALUE = 2; - // The session cannot be set. - SET_SESSION_OPTION_RESULT_ERROR = 3; - } - - repeated SetSessionOptionResult results = 1; -} - -message ActionGetSessionOptionsRequest { - option (experimental) = true; -} - -message ActionGetSessionOptionsResult { - option (experimental) = true; - - repeated SessionOption session_options = 1; -} - extend google.protobuf.MessageOptions { bool experimental = 1000; } From ad0afab6f6992d7b97e668607e0d98618f8c96b8 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 14 Jul 2023 10:18:39 -0700 Subject: [PATCH 013/195] Change Proto to use map of Session options --- format/Flight.proto | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/format/Flight.proto b/format/Flight.proto index 86db2f42255be..055d23c5f0812 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -528,6 +528,8 @@ message PutResult { /* * Request message for the "Close Session" action. + * + * The exiting session is referenced via a cookie header. */ message ActionCloseSessionRequest { option (experimental) = true; @@ -560,29 +562,28 @@ message ActionCloseSessionResult { CloseSessionResult result = 1; } -message SessionOption { +message SessionOptionValue { option (experimental) = true; message StringListValue { repeated string values = 1; } - string option_name = 1; oneof option_value { - string string_value = 2; - bool bool_value = 3; - sfixed32 int32_value = 4; - sfixed64 int64_value = 5; - float float_value = 6; - double double_value = 7; - StringListValue string_list_value = 8; + string string_value = 1; + bool bool_value = 2; + sfixed32 int32_value = 3; + sfixed64 int64_value = 4; + float float_value = 5; + double double_value = 6; + StringListValue string_list_value = 7; } } message ActionSetSessionOptionsRequest { option (experimental) = true; - repeated SessionOption session_options = 1; + map session_options = 1; } message ActionSetSessionOptionsResult { @@ -601,7 +602,7 @@ message ActionSetSessionOptionsResult { SET_SESSION_OPTION_RESULT_ERROR = 3; } - repeated SetSessionOptionResult results = 1; + map results = 1; } message ActionGetSessionOptionsRequest { @@ -611,7 +612,7 @@ message ActionGetSessionOptionsRequest { message ActionGetSessionOptionsResult { option (experimental) = true; - repeated SessionOption session_options = 1; + map session_options = 1; } extend google.protobuf.MessageOptions { From 66ad805dd34caa69e922ab076eaf0919414cf9cf Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 14 Jul 2023 16:16:42 -0700 Subject: [PATCH 014/195] FSQL Client: Use SessionOptions PB Map --- cpp/src/arrow/flight/sql/client.cc | 56 +++++++++++++++--------------- cpp/src/arrow/flight/sql/client.h | 4 +-- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index 8fc2fd12480f9..e26df5c5a814d 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -800,42 +800,42 @@ ::arrow::Result FlightSqlClient::CancelQuery( ::arrow::Result> FlightSqlClient::SetSessionOptions( const FlightCallOptions& options, - const std::vector& session_options) { + const std::map& session_options) { pb::ActionSetSessionOptionsRequest request; - for (const SessionOption& in_opt : session_options) { - pb::SessionOption* opt = request.add_session_options(); - const std::string& name = in_opt.option_name; - opt->set_option_name(name); + auto* options_map = request->mutable_session_options(); - const SessionOptionValue& value = in_opt.option_value; + for (const auto & [name, value] : session_options) { if (value.index() == std::variant_npos) return Status::Invalid("Undefined SessionOptionValue type "); + + pb:SessionOptionValue pb_val; switch (static_cast(value.index())) { case SessionOptionValueType::kString: - opt->set_string_value(std::get(value)); + pb_val->set_string_value(std::get(value)); break; case SessionOptionValueType::kBool: - opt->set_bool_value(std::get(value)); + pb_val->set_bool_value(std::get(value)); break; case SessionOptionValueType::kInt32: - opt->set_int32_value(std::get(value)); + pb_val->set_int32_value(std::get(value)); break; case SessionOptionValueType::kInt64: - opt->set_int64_value(std::get(value)); + pb_val->set_int64_value(std::get(value)); break; case SessionOptionValueType::kFloat: - opt->set_float_value(std::get(value)); + pb_val->set_float_value(std::get(value)); break; case SessionOptionValueType::kDouble: - opt->set_double_value(std::get(value)); + pb_val->set_double_value(std::get(value)); break; case SessionOptionValueType::kStringList: pb::SessionOption::StringListValue* string_list_value = - opt->mutable_string_list_value(); + pb_val->mutable_string_list_value(); for (const std::string& s : std::get>(value)) string_list_value->add_values(s); break; } + (*options_map)[in_opt.option_name] = std::move(pb_value); } std::unique_ptr results; @@ -868,7 +868,7 @@ ::arrow::Result> FlightSqlClient::SetSession return result; } -::arrow::Result> FlightSqlClient::GetSessionOptions ( +::arrow::Result> FlightSqlClient::GetSessionOptions ( const FlightCallOptions& options) { pb::ActionGetSessionOptionsRequest request; @@ -880,42 +880,42 @@ ::arrow::Result> FlightSqlClient::GetSessionOptions ( ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); - std::vector result; + std::map result; if (pb_result.session_options_size() > 0) { result.reserve(pb_result.session_options_size()); - for (const pb::SessionOption& in_opt : pb_result.session_options()) { - const std::string& name = in_opt.option_name(); + for (auto& [pb_opt_name, pb_opt_val] : pb_result.session_options()) { SessionOptionValue val; - switch (in_opt.option_value_case()) { + switch (pb_value.option_value_case()) { case pb::SessionOption::OPTION_VALUE_NOT_SET: - return Status::Invalid("Unset option_value for name '" + name + "'"); + return Status::Invalid("Unset option_value for name '" + pb_opt_name + "'"); case pb::SessionOption::kStringValue: - val = in_opt.string_value(); + val = pb_opt_val.string_value(); break; case pb::SessionOption::kBoolValue: - val = in_opt.bool_value(); + val = pb_opt_val.bool_value(); break; case pb::SessionOption::kInt32Value: - val = in_opt.int32_value(); + val = pb_opt_val.int32_value(); break; case pb::SessionOption::kInt64Value: - val = in_opt.int64_value(); + val = pb_opt_val.int64_value(); break; case pb::SessionOption::kFloatValue: - val = in_opt.float_value(); + val = pb_opt_val.float_value(); break; case pb::SessionOption::kDoubleValue: - val = in_opt.double_value(); + val = pb_opt_val.double_value(); break; case pb::SessionOption::kStringListValue: val.emplace>(); + // ??? std::get>(val) - .reserve(in_opt.string_list_value().values_size()); - for (const std::string& s : in_opt.string_list_value().values()) + .reserve(pb_opt_val.string_list_value().values_size()); + for (const std::string& s : pb_opt_val.string_list_value().values()) std::get>(val).push_back(s); break; } - result.emplace_back(name, std::move(val)); + result[pb_opt_name] = std::move(val); } } diff --git a/cpp/src/arrow/flight/sql/client.h b/cpp/src/arrow/flight/sql/client.h index 3cdcc81aa72ae..086c640d92cfb 100644 --- a/cpp/src/arrow/flight/sql/client.h +++ b/cpp/src/arrow/flight/sql/client.h @@ -356,12 +356,12 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlClient { /// \param[in] session_options The session options to set. ::arrow::Result> SetSessionOptions( const FlightCallOptions& options, - const std::vector& session_options); + const std::map& session_options); /// \brief Gets current session options. /// /// \param[in] options RPC-layer hints for this call. - ::arrow::Result> GetSessionOptions( + ::arrow::Result> GetSessionOptions( const FlightCallOptions& options); /// \brief Explicitly closes the session if applicable. From d6005a14dbfbb604d202ebf7681103bbda7d0f2a Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 14 Jul 2023 16:39:59 -0700 Subject: [PATCH 015/195] FSQL Server: Use SessionOptions PB Map (incomplete?) --- cpp/src/arrow/flight/sql/server.cc | 42 +++++++++++++++--------------- cpp/src/arrow/flight/sql/server.h | 6 ++--- cpp/src/arrow/flight/sql/types.h | 12 ++------- 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index 15ecccc01fbc5..f7d91ab7e0f72 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -515,65 +515,65 @@ arrow::Result PackActionResult(ActionCreatePreparedStatementResult resul arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { pb::ActionSetSessionOptionsResult pb_result; - for (const SetSessionOptionResult res : result.results) { + auto* pb_results_map = pb_result.mutable_results(); + for (const auto& [opt_name, res] : result.results) { + int val; switch (res) { case SetSessionOptionResult::kUnspecified: - pb_result.add_results( - pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED); + val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED; break; case SetSessionOptionResult::kOk: - pb_result.add_results( - pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_OK); + val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_OK; break; case SetSessionOptionResult::kInvalidResult: - pb_result.add_results( - pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_INVALID_VALUE); + val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_INVALID_VALUE; break; case SetSessionOptionResult::kError: - pb_result.add_results( - pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR); + val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR; break; } + pb_results_map[opt_name] = res_value; } return PackActionResult(pb_result); } +// FIXME arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { pb::ActionGetSessionOptionsResult pb_result; - for (const SessionOption& in_opt : result.session_options) { - pb::SessionOption* opt = pb_result.add_session_options(); - const std::string& name = in_opt.option_name; - opt->set_option_name(name); + auth* pb_results = pb_result.mutable_session_options(); + for (const auto& [name, value] : result.session_options) { + pb::SessionOptionValue pb_opt_val; - const SessionOptionValue& value = in_opt.option_value; if (value.index() == std::variant_npos) return Status::Invalid("Undefined SessionOptionValue type "); + switch ((SessionOptionValueType)(value.index())) { case SessionOptionValueType::kString: - opt->set_string_value(std::get(value)); + pb_opt_val->set_string_value(std::get(value)); break; case SessionOptionValueType::kBool: - opt->set_bool_value(std::get(value)); + pb_opt_val->set_bool_value(std::get(value)); break; case SessionOptionValueType::kInt32: - opt->set_int32_value(std::get(value)); + pb_opt_val->set_int32_value(std::get(value)); break; case SessionOptionValueType::kInt64: - opt->set_int64_value(std::get(value)); + pb_opt_val->set_int64_value(std::get(value)); break; case SessionOptionValueType::kFloat: - opt->set_float_value(std::get(value)); + pb_opt_val->set_float_value(std::get(value)); break; case SessionOptionValueType::kDouble: - opt->set_double_value(std::get(value)); + pb_opt_val->set_double_value(std::get(value)); break; case SessionOptionValueType::kStringList: pb::SessionOption::StringListValue* string_list_value = - opt->mutable_string_list_value(); + pb_opt_val->mutable_string_list_value(); for (const std::string& s : std::get>(value)) string_list_value->add_values(s); break; } + (*pb_results)[name] = std::move(opt); } return PackActionResult(pb_result); diff --git a/cpp/src/arrow/flight/sql/server.h b/cpp/src/arrow/flight/sql/server.h index bbd3a73773d66..17f582af698fc 100644 --- a/cpp/src/arrow/flight/sql/server.h +++ b/cpp/src/arrow/flight/sql/server.h @@ -230,12 +230,12 @@ struct ARROW_FLIGHT_SQL_EXPORT ActionCloseSessionRequest {}; /// \brief A request to set a set of session options by key/value. struct ARROW_FLIGHT_SQL_EXPORT ActionSetSessionOptionsRequest { - std::vector session_options; + std::map session_options; }; /// \brief The result(s) of setting session option(s). struct ARROW_FLIGHT_SQL_EXPORT ActionSetSessionOptionsResult { - std::vector results; + std::map results; }; /// \brief A request to get current session options. @@ -243,7 +243,7 @@ struct ARROW_FLIGHT_SQL_EXPORT ActionGetSessionOptionsRequest {}; /// \brief The current session options. struct ARROW_FLIGHT_SQL_EXPORT ActionGetSessionOptionsResult { - std::vector session_options; + std::map session_options; }; /// @} diff --git a/cpp/src/arrow/flight/sql/types.h b/cpp/src/arrow/flight/sql/types.h index 900e29fe45767..30bbe72e75f10 100644 --- a/cpp/src/arrow/flight/sql/types.h +++ b/cpp/src/arrow/flight/sql/types.h @@ -44,23 +44,15 @@ using SqlInfoResult = /// \brief Map SQL info identifier to its value. using SqlInfoResultMap = std::unordered_map; -/// \brief Variant supporting all possible types for SetSessionOptions +/// \brief Variant supporting all possible types for {Set,Get}SessionOptions using SessionOptionValue = std::variant>; +// FIXME obviate & remove enum struct SessionOptionValueType : size_t { kString, kBool, kInt32, kInt64, kFloat, kDouble, kStringList }; -struct ARROW_FLIGHT_SQL_EXPORT SessionOption { - std::string option_name; - SessionOptionValue option_value; - - explicit SessionOption(std::string name, SessionOptionValue val) - : option_name{ std::move(name) }, option_value{ std::move(val) } {} - SessionOption() {} -}; - /// \brief Options to be set in the SqlInfo. struct ARROW_FLIGHT_SQL_EXPORT SqlInfoOptions { /// \brief Predefined info values for GetSqlInfo. From 55c198d0778412460f79b65fb86b5c065fa27ef6 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 17 Jul 2023 17:15:53 -0700 Subject: [PATCH 016/195] [Builds] Fix build errors --- cpp/src/arrow/flight/sql/client.cc | 64 +++++++++++++++--------------- cpp/src/arrow/flight/sql/client.h | 3 +- cpp/src/arrow/flight/sql/server.cc | 64 +++++++++++++++--------------- cpp/src/arrow/flight/sql/server.h | 1 + 4 files changed, 67 insertions(+), 65 deletions(-) diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index e26df5c5a814d..71dacb37d26ba 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -798,44 +798,44 @@ ::arrow::Result FlightSqlClient::CancelQuery( return Status::IOError("Server returned unknown result ", result.result()); } -::arrow::Result> FlightSqlClient::SetSessionOptions( +::arrow::Result> +FlightSqlClient::SetSessionOptions( const FlightCallOptions& options, const std::map& session_options) { pb::ActionSetSessionOptionsRequest request; - auto* options_map = request->mutable_session_options(); + auto* options_map = request.mutable_session_options(); for (const auto & [name, value] : session_options) { if (value.index() == std::variant_npos) return Status::Invalid("Undefined SessionOptionValue type "); - pb:SessionOptionValue pb_val; + pb::SessionOptionValue pb_val; switch (static_cast(value.index())) { case SessionOptionValueType::kString: - pb_val->set_string_value(std::get(value)); + pb_val.set_string_value(std::get(value)); break; case SessionOptionValueType::kBool: - pb_val->set_bool_value(std::get(value)); + pb_val.set_bool_value(std::get(value)); break; case SessionOptionValueType::kInt32: - pb_val->set_int32_value(std::get(value)); + pb_val.set_int32_value(std::get(value)); break; case SessionOptionValueType::kInt64: - pb_val->set_int64_value(std::get(value)); + pb_val.set_int64_value(std::get(value)); break; case SessionOptionValueType::kFloat: - pb_val->set_float_value(std::get(value)); + pb_val.set_float_value(std::get(value)); break; case SessionOptionValueType::kDouble: - pb_val->set_double_value(std::get(value)); + pb_val.set_double_value(std::get(value)); break; case SessionOptionValueType::kStringList: - pb::SessionOption::StringListValue* string_list_value = - pb_val->mutable_string_list_value(); + auto* string_list_value = pb_val.mutable_string_list_value(); for (const std::string& s : std::get>(value)) string_list_value->add_values(s); break; } - (*options_map)[in_opt.option_name] = std::move(pb_value); + (*options_map)[name] = std::move(pb_val); } std::unique_ptr results; @@ -845,30 +845,34 @@ ::arrow::Result> FlightSqlClient::SetSession pb::ActionSetSessionOptionsResult pb_result; ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); - std::vector result; - for (const int result_value : pb_result.results()) { + std::map result; + for (const auto & [result_key, result_value] : pb_result.results()) { switch (result_value) { case pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED: - result.push_back(SetSessionOptionResult::kUnspecified); + result[result_key] = SetSessionOptionResult::kUnspecified; break; case pb::ActionSetSessionOptionsResult ::SET_SESSION_OPTION_RESULT_OK: - result.push_back(SetSessionOptionResult::kOk); + result[result_key] = SetSessionOptionResult::kOk; break; case pb::ActionSetSessionOptionsResult ::SET_SESSION_OPTION_RESULT_INVALID_VALUE: - result.push_back(SetSessionOptionResult::kInvalidResult); + result[result_key] = SetSessionOptionResult::kInvalidResult; break; case pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR: - result.push_back(SetSessionOptionResult::kError); + result[result_key] = SetSessionOptionResult::kError; break; + default: + return Status::IOError("Invalid SetSessionOptionResult value for key " + + result_key); } } return result; } -::arrow::Result> FlightSqlClient::GetSessionOptions ( +::arrow::Result> +FlightSqlClient::GetSessionOptions ( const FlightCallOptions& options) { pb::ActionGetSessionOptionsRequest request; @@ -880,35 +884,33 @@ ::arrow::Result> FlightSqlClient::GetS ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); - std::map result; + std::map result; if (pb_result.session_options_size() > 0) { - result.reserve(pb_result.session_options_size()); for (auto& [pb_opt_name, pb_opt_val] : pb_result.session_options()) { SessionOptionValue val; - switch (pb_value.option_value_case()) { - case pb::SessionOption::OPTION_VALUE_NOT_SET: + switch (pb_opt_val.option_value_case()) { + case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: return Status::Invalid("Unset option_value for name '" + pb_opt_name + "'"); - case pb::SessionOption::kStringValue: + case pb::SessionOptionValue::kStringValue: val = pb_opt_val.string_value(); break; - case pb::SessionOption::kBoolValue: + case pb::SessionOptionValue::kBoolValue: val = pb_opt_val.bool_value(); break; - case pb::SessionOption::kInt32Value: + case pb::SessionOptionValue::kInt32Value: val = pb_opt_val.int32_value(); break; - case pb::SessionOption::kInt64Value: + case pb::SessionOptionValue::kInt64Value: val = pb_opt_val.int64_value(); break; - case pb::SessionOption::kFloatValue: + case pb::SessionOptionValue::kFloatValue: val = pb_opt_val.float_value(); break; - case pb::SessionOption::kDoubleValue: + case pb::SessionOptionValue::kDoubleValue: val = pb_opt_val.double_value(); break; - case pb::SessionOption::kStringListValue: + case pb::SessionOptionValue::kStringListValue: val.emplace>(); - // ??? std::get>(val) .reserve(pb_opt_val.string_list_value().values_size()); for (const std::string& s : pb_opt_val.string_list_value().values()) diff --git a/cpp/src/arrow/flight/sql/client.h b/cpp/src/arrow/flight/sql/client.h index 086c640d92cfb..c6afe0217a0eb 100644 --- a/cpp/src/arrow/flight/sql/client.h +++ b/cpp/src/arrow/flight/sql/client.h @@ -19,6 +19,7 @@ #include #include +#include #include #include "arrow/flight/client.h" @@ -354,7 +355,7 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlClient { /// /// \param[in] options RPC-layer hints for this call. /// \param[in] session_options The session options to set. - ::arrow::Result> SetSessionOptions( + ::arrow::Result> SetSessionOptions( const FlightCallOptions& options, const std::map& session_options); diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index f7d91ab7e0f72..da7bdeae3caa2 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -380,40 +380,38 @@ arrow::Result ParseActionSetSessionOptionsReques ActionSetSessionOptionsRequest result; if (command.session_options_size() > 0) { - result.session_options.reserve(command.session_options_size()); - for (const pb::SessionOption& in_opt : command.session_options()) { - const std::string& name = in_opt.option_name(); + for (const auto & [name, pb_val] : command.session_options()) { SessionOptionValue val; - switch (in_opt.option_value_case()) { - case pb::SessionOption::OPTION_VALUE_NOT_SET: + switch (pb_val.option_value_case()) { + case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: return Status::Invalid("Unset SessionOptionValue for name '" + name + "'"); - case pb::SessionOption::kStringValue: - val = in_opt.string_value(); + case pb::SessionOptionValue::kStringValue: + val = pb_val.string_value(); break; - case pb::SessionOption::kBoolValue: - val = in_opt.bool_value(); + case pb::SessionOptionValue::kBoolValue: + val = pb_val.bool_value(); break; - case pb::SessionOption::kInt32Value: - val = in_opt.int32_value(); + case pb::SessionOptionValue::kInt32Value: + val = pb_val.int32_value(); break; - case pb::SessionOption::kInt64Value: - val = in_opt.int64_value(); + case pb::SessionOptionValue::kInt64Value: + val = pb_val.int64_value(); break; - case pb::SessionOption::kFloatValue: - val = in_opt.float_value(); + case pb::SessionOptionValue::kFloatValue: + val = pb_val.float_value(); break; - case pb::SessionOption::kDoubleValue: - val = in_opt.double_value(); + case pb::SessionOptionValue::kDoubleValue: + val = pb_val.double_value(); break; - case pb::SessionOption::kStringListValue: + case pb::SessionOptionValue::kStringListValue: val.emplace>(); std::get>(val) - .reserve(in_opt.string_list_value().values_size()); - for (const std::string& s : in_opt.string_list_value().values()) + .reserve(pb_val.string_list_value().values_size()); + for (const std::string& s : pb_val.string_list_value().values()) std::get>(val).push_back(s); break; } - result.session_options.emplace_back(name, std::move(val)); + result.session_options[name] = std::move(val); } } @@ -517,7 +515,7 @@ arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { pb::ActionSetSessionOptionsResult pb_result; auto* pb_results_map = pb_result.mutable_results(); for (const auto& [opt_name, res] : result.results) { - int val; + pb::ActionSetSessionOptionsResult_SetSessionOptionResult val; switch (res) { case SetSessionOptionResult::kUnspecified: val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED; @@ -532,7 +530,7 @@ arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR; break; } - pb_results_map[opt_name] = res_value; + (*pb_results_map)[opt_name] = val; } return PackActionResult(pb_result); } @@ -540,7 +538,7 @@ arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { // FIXME arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { pb::ActionGetSessionOptionsResult pb_result; - auth* pb_results = pb_result.mutable_session_options(); + auto* pb_results = pb_result.mutable_session_options(); for (const auto& [name, value] : result.session_options) { pb::SessionOptionValue pb_opt_val; @@ -549,31 +547,31 @@ arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { switch ((SessionOptionValueType)(value.index())) { case SessionOptionValueType::kString: - pb_opt_val->set_string_value(std::get(value)); + pb_opt_val.set_string_value(std::get(value)); break; case SessionOptionValueType::kBool: - pb_opt_val->set_bool_value(std::get(value)); + pb_opt_val.set_bool_value(std::get(value)); break; case SessionOptionValueType::kInt32: - pb_opt_val->set_int32_value(std::get(value)); + pb_opt_val.set_int32_value(std::get(value)); break; case SessionOptionValueType::kInt64: - pb_opt_val->set_int64_value(std::get(value)); + pb_opt_val.set_int64_value(std::get(value)); break; case SessionOptionValueType::kFloat: - pb_opt_val->set_float_value(std::get(value)); + pb_opt_val.set_float_value(std::get(value)); break; case SessionOptionValueType::kDouble: - pb_opt_val->set_double_value(std::get(value)); + pb_opt_val.set_double_value(std::get(value)); break; case SessionOptionValueType::kStringList: - pb::SessionOption::StringListValue* string_list_value = - pb_opt_val->mutable_string_list_value(); + pb::SessionOptionValue::StringListValue* string_list_value = + pb_opt_val.mutable_string_list_value(); for (const std::string& s : std::get>(value)) string_list_value->add_values(s); break; } - (*pb_results)[name] = std::move(opt); + (*pb_results)[name] = std::move(pb_opt_val); } return PackActionResult(pb_result); diff --git a/cpp/src/arrow/flight/sql/server.h b/cpp/src/arrow/flight/sql/server.h index 17f582af698fc..22cd816e91002 100644 --- a/cpp/src/arrow/flight/sql/server.h +++ b/cpp/src/arrow/flight/sql/server.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "arrow/flight/server.h" From afbe366bfa1e93850f77a8e597a6af24851dece2 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 24 Jul 2023 09:30:53 -0700 Subject: [PATCH 017/195] [BUILDS] Use visitors to convert SessionOptionValue->Proto --- cpp/src/arrow/flight/sql/client.cc | 52 ++++++++++++-------------- cpp/src/arrow/flight/sql/server.cc | 59 +++++++++++++----------------- cpp/src/arrow/flight/sql/types.h | 5 --- 3 files changed, 50 insertions(+), 66 deletions(-) diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index 71dacb37d26ba..2e01a62422f90 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -31,6 +31,12 @@ #include "arrow/result.h" #include "arrow/util/logging.h" +// Lambda helper & CTAD +template +struct overloaded : Ts... { using Ts::operator()...; }; +template // CTAD will not be needed for >=C++20 +overloaded(Ts...) -> overloaded; + namespace pb = arrow::flight::protocol; namespace flight_sql_pb = arrow::flight::protocol::sql; @@ -805,37 +811,27 @@ FlightSqlClient::SetSessionOptions( pb::ActionSetSessionOptionsRequest request; auto* options_map = request.mutable_session_options(); - for (const auto & [name, value] : session_options) { - if (value.index() == std::variant_npos) + for (const auto & [name, opt_value] : session_options) { + pb::SessionOptionValue pb_opt_value; + + if (opt_value.index() == std::variant_npos) return Status::Invalid("Undefined SessionOptionValue type "); - pb::SessionOptionValue pb_val; - switch (static_cast(value.index())) { - case SessionOptionValueType::kString: - pb_val.set_string_value(std::get(value)); - break; - case SessionOptionValueType::kBool: - pb_val.set_bool_value(std::get(value)); - break; - case SessionOptionValueType::kInt32: - pb_val.set_int32_value(std::get(value)); - break; - case SessionOptionValueType::kInt64: - pb_val.set_int64_value(std::get(value)); - break; - case SessionOptionValueType::kFloat: - pb_val.set_float_value(std::get(value)); - break; - case SessionOptionValueType::kDouble: - pb_val.set_double_value(std::get(value)); - break; - case SessionOptionValueType::kStringList: - auto* string_list_value = pb_val.mutable_string_list_value(); - for (const std::string& s : std::get>(value)) + std::visit(overloaded{ + // TODO move this somewhere common that can have Proto-involved code + [&](std::string v) { pb_opt_value.set_string_value(v); }, + [&](bool v) { pb_opt_value.set_bool_value(v); }, + [&](int32_t v) { pb_opt_value.set_int32_value(v); }, + [&](int64_t v) { pb_opt_value.set_int64_value(v); }, + [&](float v) { pb_opt_value.set_float_value(v); }, + [&](double v) { pb_opt_value.set_double_value(v); }, + [&](std::vector v) { + auto* string_list_value = pb_opt_value.mutable_string_list_value(); + for (const std::string& s : v) string_list_value->add_values(s); - break; - } - (*options_map)[name] = std::move(pb_val); + } + }, opt_value); + (*options_map)[name] = std::move(pb_opt_value); } std::unique_ptr results; diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index da7bdeae3caa2..d401532258c6b 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -33,6 +33,12 @@ #include "arrow/type.h" #include "arrow/util/checked_cast.h" +// Lambda helper & CTAD +template +struct overloaded : Ts... { using Ts::operator()...; }; +template // CTAD will not be needed for >=C++20 +overloaded(Ts...) -> overloaded; + #define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \ COMMAND.has_##PROPERTY() ? std::make_optional(COMMAND.PROPERTY()) : std::nullopt @@ -535,43 +541,30 @@ arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { return PackActionResult(pb_result); } -// FIXME arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { pb::ActionGetSessionOptionsResult pb_result; auto* pb_results = pb_result.mutable_session_options(); - for (const auto& [name, value] : result.session_options) { - pb::SessionOptionValue pb_opt_val; - - if (value.index() == std::variant_npos) - return Status::Invalid("Undefined SessionOptionValue type "); - - switch ((SessionOptionValueType)(value.index())) { - case SessionOptionValueType::kString: - pb_opt_val.set_string_value(std::get(value)); - break; - case SessionOptionValueType::kBool: - pb_opt_val.set_bool_value(std::get(value)); - break; - case SessionOptionValueType::kInt32: - pb_opt_val.set_int32_value(std::get(value)); - break; - case SessionOptionValueType::kInt64: - pb_opt_val.set_int64_value(std::get(value)); - break; - case SessionOptionValueType::kFloat: - pb_opt_val.set_float_value(std::get(value)); - break; - case SessionOptionValueType::kDouble: - pb_opt_val.set_double_value(std::get(value)); - break; - case SessionOptionValueType::kStringList: - pb::SessionOptionValue::StringListValue* string_list_value = - pb_opt_val.mutable_string_list_value(); - for (const std::string& s : std::get>(value)) + for (const auto& [name, opt_value] : result.session_options) { + pb::SessionOptionValue pb_opt_value; + + if (opt_value.index() == std::variant_npos) + return Status::Invalid("Undefined SessionOptionValue type"); + + std::visit(overloaded{ + // TODO move this somewhere common that can have Proto-involved code + [&](std::string v) { pb_opt_value.set_string_value(v); }, + [&](bool v) { pb_opt_value.set_bool_value(v); }, + [&](int32_t v) { pb_opt_value.set_int32_value(v); }, + [&](int64_t v) { pb_opt_value.set_int64_value(v); }, + [&](float v) { pb_opt_value.set_float_value(v); }, + [&](double v) { pb_opt_value.set_double_value(v); }, + [&](std::vector v) { + auto* string_list_value = pb_opt_value.mutable_string_list_value(); + for (const std::string& s : v) string_list_value->add_values(s); - break; - } - (*pb_results)[name] = std::move(pb_opt_val); + } + }, opt_value); + (*pb_results)[name] = std::move(pb_opt_value); } return PackActionResult(pb_result); diff --git a/cpp/src/arrow/flight/sql/types.h b/cpp/src/arrow/flight/sql/types.h index 30bbe72e75f10..cd566d0bb0717 100644 --- a/cpp/src/arrow/flight/sql/types.h +++ b/cpp/src/arrow/flight/sql/types.h @@ -48,11 +48,6 @@ using SqlInfoResultMap = std::unordered_map; using SessionOptionValue = std::variant>; -// FIXME obviate & remove -enum struct SessionOptionValueType : size_t { - kString, kBool, kInt32, kInt64, kFloat, kDouble, kStringList -}; - /// \brief Options to be set in the SqlInfo. struct ARROW_FLIGHT_SQL_EXPORT SqlInfoOptions { /// \brief Predefined info values for GetSqlInfo. From 0f8d8c065a221bc272795942b4cb9a70a116a744 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 10 Aug 2023 12:25:26 -0700 Subject: [PATCH 018/195] Change to string_view for interfaces --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 6 +++--- cpp/src/arrow/flight/sql/server_session_middleware.h | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 4e80cad3e8db6..603a1c7915a42 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -161,15 +161,15 @@ std::shared_ptr MakeServerSessionMiddlewareFactory() { new ServerSessionMiddlewareFactory()); } -SessionOptionValue FlightSqlSession::GetSessionOption(const std::string& k) { +SessionOptionValue FlightSqlSession::GetSessionOption(const std::string_view k) { const std::shared_lock l(map_lock_); return map_.at(k); } -void FlightSqlSession::SetSessionOption(const std::string& k, const SessionOptionValue& v) { +void FlightSqlSession::SetSessionOption(const std::string_view, const SessionOptionValue& v) { const std::unique_lock l(map_lock_); map_[k] = v; } -void FlightSqlSession::EraseSessionOption(const std::string& k) { +void FlightSqlSession::EraseSessionOption(const std::string_view) { const std::unique_lock l(map_lock_); map_.erase(k); } diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index ca44e36ace910..b78d3ce53db72 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -20,6 +20,8 @@ #pragma once +#include + #include "arrow/flight/server_middleware.h" #include "arrow/flight/sql/types.h" @@ -38,11 +40,11 @@ class FlightSqlSession { std::shared_mutex map_lock_; public: /// \brief Get session option by key - SessionOptionValue GetSessionOption(const std::string&); + SessionOptionValue GetSessionOption(const std::string_view); /// \brief Set session option by key to given value - void SetSessionOption(const std::string&, const SessionOptionValue&); + void SetSessionOption(const std::string_view, const SessionOptionValue&); /// \brief Idempotently remove key from this call's Session, if Session & key exist - void EraseSessionOption(const std::string&); + void EraseSessionOption(const std::string_view); }; /// \brief A middleware to handle Session option persistence and related *Cookie headers. From bd8095cd2a6e3762ead989ae2c09e5592792b671 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 22 Oct 2023 14:58:02 -0700 Subject: [PATCH 019/195] WIP: High-level design review ONLY --- cpp/src/arrow/flight/client.cc | 212 ++++++++++++++++++ .../arrow/flight/serialization_internal.cc | 28 +++ cpp/src/arrow/flight/sql/client.cc | 144 +----------- cpp/src/arrow/flight/sql/client.h | 18 +- cpp/src/arrow/flight/sql/server.cc | 82 ++++--- cpp/src/arrow/flight/sql/server.h | 37 +-- .../flight/sql/server_session_middleware.cc | 2 +- .../flight/sql/server_session_middleware.h | 2 +- cpp/src/arrow/flight/sql/types.h | 20 -- cpp/src/arrow/flight/types.cc | 169 ++++++++++++++ cpp/src/arrow/flight/types.h | 172 ++++++++++++++ 11 files changed, 644 insertions(+), 242 deletions(-) diff --git a/cpp/src/arrow/flight/client.cc b/cpp/src/arrow/flight/client.cc index 25da5e8007660..e965e2b8e6e7f 100644 --- a/cpp/src/arrow/flight/client.cc +++ b/cpp/src/arrow/flight/client.cc @@ -713,6 +713,218 @@ arrow::Result FlightClient::DoExchange( return result; } +// PHOXME implement these... +arrow::Result FlightClient::SetSessionOptions( + const FlightCallOptions& options, const SetSessionOptionsRequest& request) { + RETURN_NOT_OK(CheckOpen()); + /* + */ +} + +arrow::Result FlightClient::GetSessionOptions( + const FlightCallOptions& options) { + RETURN_NOT_OK(CheckOpen()); + /* + */ +} + +arrow::Result<> FlightClient::CloseSession(const FlightCallOptions& options) { + RETURN_NOT_OK(CheckOpen()); + /* + */ +} + +::arrow::Result +FlightClient::SetSessionOptions( + const FlightCallOptions& options, + const std::map& session_options) { + RETURN_NOT_OK(CheckOpen()); + RETURN_NOT_OK(CheckOpen()); + ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); + Action action{ActionType::kSetSessionOptions.type, Buffer::FromString(body)}; + ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); + ARROW_ASSIGN_OR_RAISE(auto result, stream->Next()); + ARROW_ASSIGN_OR_RAISE(auto set_session_options_result, + CloseSessionResult::Deserialize( + std::string_view(*result->body))); + ARROW_RETURN_NOT_OK(stream->Drain()); + return std::move(set_session_options_result); /* PHOXME: take anything from here then delete this code... + pb::SetSessionOptionsRequest request; + auto* options_map = request.mutable_session_options(); + + for (const auto & [name, opt_value] : session_options) { + pb::SessionOptionValue pb_opt_value; + + if (opt_value.index() == std::variant_npos) + return Status::Invalid("Undefined SessionOptionValue type "); + + std::visit(overloaded{ + // TODO move this somewhere common that can have Proto-involved code + [&](std::string v) { pb_opt_value.set_string_value(v); }, + [&](bool v) { pb_opt_value.set_bool_value(v); }, + [&](int32_t v) { pb_opt_value.set_int32_value(v); }, + [&](int64_t v) { pb_opt_value.set_int64_value(v); }, + [&](float v) { pb_opt_value.set_float_value(v); }, + [&](double v) { pb_opt_value.set_double_value(v); }, + [&](std::vector v) { + auto* string_list_value = pb_opt_value.mutable_string_list_value(); + for (const std::string& s : v) + string_list_value->add_values(s); + } + }, opt_value); + (*options_map)[name] = std::move(pb_opt_value); + } + + + + std::unique_ptr results; + ARROW_ASSIGN_OR_RAISE(auto action, PackAction("SetSessionOptions", request)); + ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); + + + + pb::SetSessionOptionsResult pb_result; + ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); + ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); + std::map result; + + for (const auto & [result_key, result_value] : pb_result.results()) { + switch (result_value) { + case pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED: + result[result_key] = SetSessionOptionResult::kUnspecified; + break; + case pb::SetSessionOptionsResult + ::SET_SESSION_OPTION_RESULT_OK: + result[result_key] = SetSessionOptionResult::kOk; + break; + case pb::SetSessionOptionsResult + ::SET_SESSION_OPTION_RESULT_INVALID_VALUE: + result[result_key] = SetSessionOptionResult::kInvalidResult; + break; + case pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR: + result[result_key] = SetSessionOptionResult::kError; + break; + default: + return Status::IOError("Invalid SetSessionOptionResult value for key " + + result_key); + } + } + */ +} + +::arrow::Result +FlightClient::GetSessionOptions ( + const FlightCallOptions& options) { + RETURN_NOT_OK(CheckOpen()); + RETURN_NOT_OK(CheckOpen()); + ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); + Action action{ActionType::kGetSessionOptions.type, Buffer::FromString(body)}; + ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); + ARROW_ASSIGN_OR_RAISE(auto result, stream->Next()); + ARROW_ASSIGN_OR_RAISE(auto get_session_options_result, + CloseSessionResult::Deserialize( + std::string_view(*result->body))); + ARROW_RETURN_NOT_OK(stream->Drain()); + return std::move(get_session_options_result); + /* PHOXME: take anything from here then delete this code... + pb::GetSessionOptionsRequest request; + + std::unique_ptr results; + ARROW_ASSIGN_OR_RAISE(auto action, PackAction("GetSessionOptions", request)); + ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); + + pb::GetSessionOptionsResult pb_result; + ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); + ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); + + std::map result; + if (pb_result.session_options_size() > 0) { + for (auto& [pb_opt_name, pb_opt_val] : pb_result.session_options()) { + SessionOptionValue val; + switch (pb_opt_val.option_value_case()) { + case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: + return Status::Invalid("Unset option_value for name '" + pb_opt_name + "'"); + case pb::SessionOptionValue::kStringValue: + val = pb_opt_val.string_value(); + break; + case pb::SessionOptionValue::kBoolValue: + val = pb_opt_val.bool_value(); + break; + case pb::SessionOptionValue::kInt32Value: + val = pb_opt_val.int32_value(); + break; + case pb::SessionOptionValue::kInt64Value: + val = pb_opt_val.int64_value(); + break; + case pb::SessionOptionValue::kFloatValue: + val = pb_opt_val.float_value(); + break; + case pb::SessionOptionValue::kDoubleValue: + val = pb_opt_val.double_value(); + break; + case pb::SessionOptionValue::kStringListValue: + val.emplace>(); + std::get>(val) + .reserve(pb_opt_val.string_list_value().values_size()); + for (const std::string& s : pb_opt_val.string_list_value().values()) + std::get>(val).push_back(s); + break; + } + result[pb_opt_name] = std::move(val); + } + } + + return result; + */ +} + +::arrow::Result FlightClient::CloseSession( + const FlightCallOptions& options) { + RETURN_NOT_OK(CheckOpen()); + ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); + Action action{ActionType::kCloseSession.type, Buffer::FromString(body)}; + ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); + ARROW_ASSIGN_OR_RAISE(auto result, stream->Next()); + ARROW_ASSIGN_OR_RAISE(auto close_session_result, + CloseSessionResult::Deserialize( + std::string_view(*result->body))); + ARROW_RETURN_NOT_OK(stream->Drain()); + return std::move(close_session_result); +} + + +/* PHOXME: take anything from here then delete this code... + pb::CloseSessionRequest request; + + std::unique_ptr results; + ARROW_ASSIGN_OR_RAISE(auto action, PackAction("CloseSession", request)); + ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); + + pb::ActionCloseSessionResult result; + ARROW_RETURN_NOT_OK(ReadResult(results.get(), &result)); + ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); + switch (result.result()) { + case pb::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED: + return CloseSessionResult::kUnspecified; + case pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSED: + return CloseSessionResult::kClosed; + case pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSING: + return CloseSessionResult::kClosing; + case pb::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE: + return CloseSessionResult::kNotClosable; + default: + break; + } + + return Status::IOError("Server returned unknown result ", result.result()); */ + +// /PHOXME + + + + + + Status FlightClient::Close() { if (!closed_) { closed_ = true; diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index e5a7503a6386b..4476f60bc5a8f 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -379,6 +379,34 @@ Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out) { *out = Buffer::FromString(std::move(str_descr)); return Status::OK(); } +// ================================================================================================== // +// PHOXME I think most of the enum types will just get static_cast<>() as in (I think?) the CancelFlightInfo code...?? +// SessionOptionValue + +// SetSessionOptionsRequest +// FIXME I still need to move the underlying types into types.{h,cc} to be referenced from here +// FIXME as above I still need to write code to convert SessionOptionValues; debatable if a corresponding map is something to break out (probably??) + +Status FromProto(const pb::SetSessionOptionsRequest& pb_request, + pb::SetSessionOptionsRequest* request) { + +} + +Status ToProto(const SetSessionOptionsRequest request, + pb::SetSessionOptionsRequest* pb_request) { + +} + +// SetSessionOptionsResult + +// GetSessionOptionsRequest + +// GetSessionOptionsResult + +// CloseSessionResult + + +// ================================================================================================== // } // namespace internal } // namespace flight diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index 2e01a62422f90..c3f141bc1e7e6 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -804,149 +804,7 @@ ::arrow::Result FlightSqlClient::CancelQuery( return Status::IOError("Server returned unknown result ", result.result()); } -::arrow::Result> -FlightSqlClient::SetSessionOptions( - const FlightCallOptions& options, - const std::map& session_options) { - pb::ActionSetSessionOptionsRequest request; - auto* options_map = request.mutable_session_options(); - - for (const auto & [name, opt_value] : session_options) { - pb::SessionOptionValue pb_opt_value; - - if (opt_value.index() == std::variant_npos) - return Status::Invalid("Undefined SessionOptionValue type "); - - std::visit(overloaded{ - // TODO move this somewhere common that can have Proto-involved code - [&](std::string v) { pb_opt_value.set_string_value(v); }, - [&](bool v) { pb_opt_value.set_bool_value(v); }, - [&](int32_t v) { pb_opt_value.set_int32_value(v); }, - [&](int64_t v) { pb_opt_value.set_int64_value(v); }, - [&](float v) { pb_opt_value.set_float_value(v); }, - [&](double v) { pb_opt_value.set_double_value(v); }, - [&](std::vector v) { - auto* string_list_value = pb_opt_value.mutable_string_list_value(); - for (const std::string& s : v) - string_list_value->add_values(s); - } - }, opt_value); - (*options_map)[name] = std::move(pb_opt_value); - } - - std::unique_ptr results; - ARROW_ASSIGN_OR_RAISE(auto action, PackAction("SetSessionOptions", request)); - ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); - - pb::ActionSetSessionOptionsResult pb_result; - ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); - ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); - std::map result; - for (const auto & [result_key, result_value] : pb_result.results()) { - switch (result_value) { - case pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED: - result[result_key] = SetSessionOptionResult::kUnspecified; - break; - case pb::ActionSetSessionOptionsResult - ::SET_SESSION_OPTION_RESULT_OK: - result[result_key] = SetSessionOptionResult::kOk; - break; - case pb::ActionSetSessionOptionsResult - ::SET_SESSION_OPTION_RESULT_INVALID_VALUE: - result[result_key] = SetSessionOptionResult::kInvalidResult; - break; - case pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR: - result[result_key] = SetSessionOptionResult::kError; - break; - default: - return Status::IOError("Invalid SetSessionOptionResult value for key " - + result_key); - } - } - - return result; -} - -::arrow::Result> -FlightSqlClient::GetSessionOptions ( - const FlightCallOptions& options) { - pb::ActionGetSessionOptionsRequest request; - - std::unique_ptr results; - ARROW_ASSIGN_OR_RAISE(auto action, PackAction("GetSessionOptions", request)); - ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); - - pb::ActionGetSessionOptionsResult pb_result; - ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); - ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); - - std::map result; - if (pb_result.session_options_size() > 0) { - for (auto& [pb_opt_name, pb_opt_val] : pb_result.session_options()) { - SessionOptionValue val; - switch (pb_opt_val.option_value_case()) { - case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: - return Status::Invalid("Unset option_value for name '" + pb_opt_name + "'"); - case pb::SessionOptionValue::kStringValue: - val = pb_opt_val.string_value(); - break; - case pb::SessionOptionValue::kBoolValue: - val = pb_opt_val.bool_value(); - break; - case pb::SessionOptionValue::kInt32Value: - val = pb_opt_val.int32_value(); - break; - case pb::SessionOptionValue::kInt64Value: - val = pb_opt_val.int64_value(); - break; - case pb::SessionOptionValue::kFloatValue: - val = pb_opt_val.float_value(); - break; - case pb::SessionOptionValue::kDoubleValue: - val = pb_opt_val.double_value(); - break; - case pb::SessionOptionValue::kStringListValue: - val.emplace>(); - std::get>(val) - .reserve(pb_opt_val.string_list_value().values_size()); - for (const std::string& s : pb_opt_val.string_list_value().values()) - std::get>(val).push_back(s); - break; - } - result[pb_opt_name] = std::move(val); - } - } - - return result; -} - -::arrow::Result FlightSqlClient::CloseSession( - const FlightCallOptions& options) { - pb::ActionCloseSessionRequest request; - - std::unique_ptr results; - ARROW_ASSIGN_OR_RAISE(auto action, PackAction("CloseSession", request)); - ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); - - pb::ActionCloseSessionResult result; - ARROW_RETURN_NOT_OK(ReadResult(results.get(), &result)); - ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); - switch (result.result()) { - case pb::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED: - return CloseSessionResult::kUnspecified; - case pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSED: - return CloseSessionResult::kClosed; - case pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSING: - return CloseSessionResult::kClosing; - case pb::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE: - return CloseSessionResult::kNotClosable; - default: - break; - } - - return Status::IOError("Server returned unknown result ", result.result()); -} - + Status FlightSqlClient::Close() { return impl_->Close(); } std::ostream& operator<<(std::ostream& os, CancelResult result) { diff --git a/cpp/src/arrow/flight/sql/client.h b/cpp/src/arrow/flight/sql/client.h index c6afe0217a0eb..f16ee47cbe5fa 100644 --- a/cpp/src/arrow/flight/sql/client.h +++ b/cpp/src/arrow/flight/sql/client.h @@ -350,25 +350,31 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlClient { "may need to use CancelQuery() and/or CancelFlightInfo()") ::arrow::Result CancelQuery(const FlightCallOptions& options, const FlightInfo& info); - + /// \brief Sets session options. /// /// \param[in] options RPC-layer hints for this call. /// \param[in] session_options The session options to set. - ::arrow::Result> SetSessionOptions( + ::arrow::Result SetSessionOptions( const FlightCallOptions& options, - const std::map& session_options); + const std::map& session_options) { + return impl_->SetSessionOptions(options, session_options); + } /// \brief Gets current session options. /// /// \param[in] options RPC-layer hints for this call. - ::arrow::Result> GetSessionOptions( - const FlightCallOptions& options); + ::arrow::Result GetSessionOptions( + const FlightCallOptions& options) { + return impl_->GetSessionOptions(options); + } /// \brief Explicitly closes the session if applicable. /// /// \param[in] options RPC-layer hints for this call. - ::arrow::Result CloseSession(const FlightCallOptions& options); + ::arrow::Result CloseSession(const FlightCallOptions& options) { + return impl_->CloseSession(options); + } /// \brief Extends the expiration of a FlightEndpoint. /// diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index d401532258c6b..a9703bc314ee6 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -276,14 +276,14 @@ arrow::Result ParseActionCancelQueryRequest( return result; } -arrow::Result ParseActionCloseSessionRequest( +arrow::Result ParseActionCloseSessionRequest( const google::protobuf::Any& any) { - pb::ActionCloseSessionRequest command; + pb::CloseSessionRequest command; if (!any.UnpackTo(&command)) { - return Status::Invalid("Unable to unpack ActionCloseSessionRequest"); + return Status::Invalid("Unable to unpack CloseSessionRequest"); } - ActionCloseSessionRequest result; + CloseSessionRequest result; return result; } @@ -377,14 +377,14 @@ arrow::Result ParseActionEndTransactionRequest( return result; } -arrow::Result ParseActionSetSessionOptionsRequest( +arrow::Result ParseActionSetSessionOptionsRequest( const google::protobuf::Any& any) { - pb::ActionSetSessionOptionsRequest command; + pb::SetSessionOptionsRequest command; if (!any.UnpackTo(&command)) { - return Status::Invalid("Unable to unpack ActionSetSessionOptionsRequest"); + return Status::Invalid("Unable to unpack SetSessionOptionsRequest"); } - ActionSetSessionOptionsRequest result; + SetSessionOptionsRequest result; if (command.session_options_size() > 0) { for (const auto & [name, pb_val] : command.session_options()) { SessionOptionValue val; @@ -424,14 +424,14 @@ arrow::Result ParseActionSetSessionOptionsReques return result; } -arrow::Result ParseActionGetSessionOptionsRequest( +arrow::Result ParseActionGetSessionOptionsRequest( const google::protobuf::Any& any) { - pb::ActionGetSessionOptionsRequest command; + pb::GetSessionOptionsRequest command; if (!any.UnpackTo(&command)) { - return Status::Invalid("Unable to unpack ActionGetSessionOptionsRequest"); + return Status::Invalid("Unable to unpack GetSessionOptionsRequest"); } - ActionGetSessionOptionsRequest result; + GetSessionOptionsRequest result; return result; } @@ -517,23 +517,23 @@ arrow::Result PackActionResult(ActionCreatePreparedStatementResult resul return PackActionResult(pb_result); } -arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { - pb::ActionSetSessionOptionsResult pb_result; +arrow::Result PackActionResult(SetSessionOptionsResult result) { + pb::SetSessionOptionsResult pb_result; auto* pb_results_map = pb_result.mutable_results(); for (const auto& [opt_name, res] : result.results) { pb::ActionSetSessionOptionsResult_SetSessionOptionResult val; switch (res) { case SetSessionOptionResult::kUnspecified: - val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED; + val = pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED; break; case SetSessionOptionResult::kOk: - val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_OK; + val = pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_OK; break; case SetSessionOptionResult::kInvalidResult: - val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_INVALID_VALUE; + val = pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_INVALID_VALUE; break; case SetSessionOptionResult::kError: - val = pb::ActionSetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR; + val = pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR; break; } (*pb_results_map)[opt_name] = val; @@ -541,8 +541,8 @@ arrow::Result PackActionResult(ActionSetSessionOptionsResult result) { return PackActionResult(pb_result); } -arrow::Result PackActionResult(ActionGetSessionOptionsResult result) { - pb::ActionGetSessionOptionsResult pb_result; +arrow::Result PackActionResult(GetSessionOptionsResult result) { + pb::GetSessionOptionsResult pb_result; auto* pb_results = pb_result.mutable_session_options(); for (const auto& [name, opt_value] : result.session_options) { pb::SessionOptionValue pb_opt_value; @@ -942,27 +942,25 @@ Status FlightSqlServerBase::DoAction(const ServerCallContext& context, ARROW_ASSIGN_OR_RAISE(auto packed_result, PackActionResult(renewed_endpoint)); results.push_back(std::move(packed_result)); - } else if (action.type == FlightSqlServerBase::kCloseSessionActionType.type) { - ARROW_ASSIGN_OR_RAISE(ActionCloseSessionRequest internal_command, - ParseActionCloseSessionRequest(any)); - ARROW_ASSIGN_OR_RAISE(CloseSessionResult result, CloseSession(context, internal_command)); - ARROW_ASSIGN_OR_RAISE(Result packed_result, PackActionResult(std::move(result))); + } else if (action.type == ActionType::kSetSessionOptions.type) { + std::string_view body(*action.body); + ARROW_ASSIGN_OR_RAISE(auto request, SetSessionOptionsRequest::Deserialize(body)); + ARROW_ASSIGN_OR_RAISE(auto result, SetSessionOptions(context, request)); + ARROW_ASSIGN_OR_RAISE(auto packed_result, PackActionResult(std::move(result))); results.push_back(std::move(packed_result)); - } else if (action.type == FlightSqlServerBase::kSetSessionOptionsActionType.type) { - ARROW_ASSIGN_OR_RAISE(ActionSetSessionOptionsRequest internal_command, - ParseActionSetSessionOptionsRequest(any)); - ARROW_ASSIGN_OR_RAISE(ActionSetSessionOptionsResult result, - SetSessionOptions(context, internal_command)); - ARROW_ASSIGN_OR_RAISE(Result packed_result, PackActionResult(std::move(result))); + } else if (action.type == ActionType::kGetSessionOptions.type) { + std::string_view body(*action.body); + ARROW_ASSIGN_OR_RAISE(auto request, GetSessionOptionsRequest::Deserialize(body));) + ARROW_ASSIGN_OR_RAISE(auto result, GetSessionOptions(context, request)); + ARROW_ASSIGN_OR_RAISE(auto packed_result, PackActionResult(std::move(result))); results.push_back(std::move(packed_result)); - } else if (action.type == FlightSqlServerBase::kGetSessionOptionsActionType.type) { - ARROW_ASSIGN_OR_RAISE(ActionGetSessionOptionsRequest internal_command, - ParseActionGetSessionOptionsRequest(any)); - ARROW_ASSIGN_OR_RAISE(ActionGetSessionOptionsResult result, - GetSessionOptions(context, internal_command)); - ARROW_ASSIGN_OR_RAISE(Result packed_result, PackActionResult(std::move(result))); + } else if (action.type == ActionType::kCloseSession.type) { + std::string_view body(*action.body); + ARROW_ASSIGN_OR_RAISE(auto request, CloseSessionRequest::Deserialize(body)); + ARROW_ASSIGN_OR_RAISE(auto result, CloseSession(context, request)); + ARROW_ASSIGN_OR_RAISE(auto packed_result, PackActionResult(std::move(result))); results.push_back(std::move(packed_result)); } else { @@ -1273,7 +1271,7 @@ arrow::Result FlightSqlServerBase::RenewFlightEndpoint( arrow::Result FlightSqlServerBase::CloseSession( const ServerCallContext& context, - const ActionCloseSessionRequest& request) { + const CloseSessionRequest& request) { return Status::NotImplemented("CloseSession not implemented"); } @@ -1307,15 +1305,15 @@ Status FlightSqlServerBase::EndTransaction(const ServerCallContext& context, return Status::NotImplemented("EndTransaction not implemented"); } -arrow::Result FlightSqlServerBase::SetSessionOptions ( +arrow::Result FlightSqlServerBase::SetSessionOptions ( const ServerCallContext& context, - const ActionSetSessionOptionsRequest& request) { + const SetSessionOptionsRequest& request) { return Status::NotImplemented("SetSessionOptions not implemented"); } -arrow::Result FlightSqlServerBase::GetSessionOptions ( +arrow::Result FlightSqlServerBase::GetSessionOptions ( const ServerCallContext& context, - const ActionGetSessionOptionsRequest& request) { + const GetSessionOptionsRequest& request) { return Status::NotImplemented("GetSessionOptions not implemented"); } diff --git a/cpp/src/arrow/flight/sql/server.h b/cpp/src/arrow/flight/sql/server.h index 22cd816e91002..411106cae9c0b 100644 --- a/cpp/src/arrow/flight/sql/server.h +++ b/cpp/src/arrow/flight/sql/server.h @@ -226,27 +226,6 @@ struct ARROW_FLIGHT_SQL_EXPORT ActionCreatePreparedStatementResult { std::string prepared_statement_handle; }; -/// \brief A request to close the open client session. -struct ARROW_FLIGHT_SQL_EXPORT ActionCloseSessionRequest {}; - -/// \brief A request to set a set of session options by key/value. -struct ARROW_FLIGHT_SQL_EXPORT ActionSetSessionOptionsRequest { - std::map session_options; -}; - -/// \brief The result(s) of setting session option(s). -struct ARROW_FLIGHT_SQL_EXPORT ActionSetSessionOptionsResult { - std::map results; -}; - -/// \brief A request to get current session options. -struct ARROW_FLIGHT_SQL_EXPORT ActionGetSessionOptionsRequest {}; - -/// \brief The current session options. -struct ARROW_FLIGHT_SQL_EXPORT ActionGetSessionOptionsResult { - std::map session_options; -}; - /// @} /// \brief A utility function to create a ticket (a opaque binary @@ -626,23 +605,23 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlServerBase : public FlightServerBase { /// \brief Set server session option(s). /// \param[in] context The call context. /// \param[in] request The session options to set. - virtual arrow::Result SetSessionOptions( + virtual arrow::Result SetSessionOptions( const ServerCallContext& context, - const ActionSetSessionOptionsRequest& request); + const SetSessionOptionsRequest& request); /// \brief Get server session option(s). /// \param[in] context The call context. /// \param[in] request Request object. - virtual arrow::Result GetSessionOptions( + virtual arrow::Result GetSessionOptions( const ServerCallContext& context, - const ActionGetSessionOptionsRequest& request); + const GetSessionOptionsRequest& request); /// \brief Close/invalidate the session. /// \param[in] context The call context. /// \param[in] request Request object. virtual arrow::Result CloseSession( const ServerCallContext& context, - const ActionCloseSessionRequest& request); + const CloseSessionRequest& request); /// \brief Attempt to explicitly cancel a query. /// @@ -728,7 +707,7 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlServerBase : public FlightServerBase { const ActionType kCloseSessionActionType = ActionType{"CloseSession", "Explicitly close an open session.\n" - "Request Message: ActionCloseSessionRequest\n" + "Request Message: CloseSessionRequest\n" "Response Message: ActionCloseSessionResult"}; const ActionType kEndSavepointActionType = ActionType{"EndSavepoint", @@ -743,8 +722,8 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlServerBase : public FlightServerBase { const ActionType kSetSessionOptionsActionType = ActionType{"SetSessionOptions", "Set a series of session options.\n" - "Request Message: ActionSetSessionOptionsRequest\n" - "Response Message: ActionSetSessionOptionsResult"}; + "Request Message: SetSessionOptionsRequest\n" + "Response Message: SetSessionOptionsResult"}; const ActionType kGetSessionOptionsActionType = ActionType{"GetSessionOption", "Get a series of session options.\n" diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 603a1c7915a42..74c47704d7722 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -176,4 +176,4 @@ void FlightSqlSession::EraseSessionOption(const std::string_view) { } // namespace sql } // namespace flight -} // namespace arrow \ No newline at end of file +} // namespace arrow diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index b78d3ce53db72..41f8736d4fc78 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -87,4 +87,4 @@ MakeServerSessionMiddlewareFactory(); } // namespace sql } // namespace flight -} // namespace arrow \ No newline at end of file +} // namespace arrow diff --git a/cpp/src/arrow/flight/sql/types.h b/cpp/src/arrow/flight/sql/types.h index cd566d0bb0717..b41488b68f232 100644 --- a/cpp/src/arrow/flight/sql/types.h +++ b/cpp/src/arrow/flight/sql/types.h @@ -44,10 +44,6 @@ using SqlInfoResult = /// \brief Map SQL info identifier to its value. using SqlInfoResultMap = std::unordered_map; -/// \brief Variant supporting all possible types for {Set,Get}SessionOptions -using SessionOptionValue = - std::variant>; - /// \brief Options to be set in the SqlInfo. struct ARROW_FLIGHT_SQL_EXPORT SqlInfoOptions { /// \brief Predefined info values for GetSqlInfo. @@ -924,22 +920,6 @@ enum class CancelResult : int8_t { kNotCancellable, }; -/// \brief The result of setting a session option. -enum class SetSessionOptionResult : int8_t { - kUnspecified, - kOk, - kInvalidResult, - kError -}; - -/// \brief The result of closing a session. -enum class CloseSessionResult : int8_t { - kUnspecified, - kClosed, - kClosing, - kNotClosable -}; - ARROW_FLIGHT_SQL_EXPORT std::ostream& operator<<(std::ostream& os, CancelResult result); diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 1d43c41b69d9f..b06be84912ba1 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -473,6 +473,154 @@ arrow::Result CancelFlightInfoRequest::Deserialize( return out; } + + + +// PHOXME impl... +std::string SetSessionOptionsRequest::ToString() const { + std::stringstream ss; + + ss << ""; + + return ss.str(); +} +bool SetSessionOptionsRequest::Equals(const SetSessionOptionsRequest& other) const { + // compare map equality including variant types not just value equality + // PHOXME +} +arrow::Result +SetSessionOptionsRequest::SerializeToString() const { + pb::SetSessionOptionsRequest pb_request; + RETURN_NOT_OK(internal::ToProto(*this, &pb_request)); + + std::string out; + if (!pb_request.SerializeToString(&out)) { + return Status::IOError("Serialized SetSessionOptionsRequest exceeded 2GiB limit"); + } + return out; +} +static arrow::Result +SetSessionOptionsRequest::Deserialize(std::string_view serialized) {} + + + +std::string SetSessionOptionsResult::ToString() const {} +bool SetSessionOptionsResult::Equals(const SetSessionOptionsResult& other) const { + // Simple comparison with fixed types + if (results != other.results) { + return false; + } + return true; +} +arrow::Result +SetSessionOptionsResult::SerializeToString() const { + pb::SetSessionOptionsResult pb_result; + RETURN_NOT_OK(internal::ToProto(*this, &pb_result)); + + std::string out; + if (!pb_result.SerializeToString(&out)) { + return Status::IOError("Serialized SetSessionOptionsResult exceeded 2GiB limit"); + } + return out; +} +static arrow::Result +SetSessionOptionsResult::Deserialize(std::string_view serialized) {} + + + +std::string GetSessionOptionsRequest::ToString() const { + return true; +} +bool GetSessionOptionsRequest::Equals(const GetSessionOptionsRequest& other) const {} +arrow::Result +GetSessionOptionsRequest::SerializeToString() const { + pb::GetSessionOptionsRequest pb_request; + RETURN_NOT_OK(internal::ToProto(*this, &pb_request)); + + std::string out; + if (!pb_request.SerializeToString(&out)) { + return Status::IOError("Serialized GetSessionOptionsRequest exceeded 2GiB limit"); + } + return out; +} +static arrow::Result +GetSessionOptionsRequest::Deserialize(std::string_view serialized) {} + + + +std::string GetSessionOptionsResult::ToString() const { + // compare map equality including variant types not just value equality +} +bool GetSessionOptionsResult::Equals(const GetSessionOptionsResult& other) const { + // compare map equality including variant types not just value equality + // PHOXME +} +arrow::Result +GetSessionOptionsResult::SerializeToString() const { + pb::GetSessionOptionsResult pb_result; + RETURN_NOT_OK(internal::ToProto(*this, &pb_result)); + + std::string out; + if (!pb_result.SerializeToString(&out)) { + return Status::IOError("Serialized GetSessionOptionsResult exceeded 2GiB limit"); + } + return out; +} +static arrow::Result +GetSessionOptionsResult::Deserialize(std::string_view serialized) {} + + + +std::string CloseSessionRequest::ToString() const {} +bool CloseSessionRequest::Equals(const CloseSessionRequest& other) const { + return true; +} +arrow::Result +CloseSessionRequest::SerializeToString() const { + pb::CloseSessionRequest pb_request; + RETURN_NOT_OK(internal::ToProto(*this, &pb_request)); + + std::string out; + if (!pb_request.SerializeToString(&out)) { + return Status::IOError("Serialized CloseSessionRequest exceeded 2GiB limit"); + } + return out; +} +static arrow::Result +CloseSessionRequest::Deserialize(std::string_view serialized) {} + + + +std::string CloseSessionResult::ToString() const {} +bool CloseSessionResult::Equals(const CloseSessionResult& other) const { + if (result != other.result) { + return false; + } +} +arrow::Result +CloseSessionResult::SerializeToString() const { + pb::CloseSessionResult pb_result; + RETURN_NOT_OK(internal::ToProto(*this, &pb_result)); + + std::string out; + if (!pb_result.SerializeToString(&out)) { + return Status::IOError("Serialized CloseSessionResult exceeded 2GiB limit"); + } + return out; +} +static arrow::Result +CloseSessionResult::Deserialize(std::string_view serialized) {} + + + + + Location::Location() { uri_ = std::make_shared(); } arrow::Result Location::Parse(const std::string& uri_string) { @@ -648,6 +796,27 @@ const ActionType ActionType::kRenewFlightEndpoint = "Extend expiration time of the given FlightEndpoint.\n" "Request Message: RenewFlightEndpointRequest\n" "Response Message: Renewed FlightEndpoint"}; +const ActionType ActionType::kSetSessionOptions = + ActionType{ + "SetSessionOptions", + "Set client session options by key/value pairs.\n" + "Request Message: SetSessionOptionsRequest\n" + "Response Message: SetSessionOptionsResult\n" + }; +const ActionType ActionType::kGetSessionOptions = + ActionType{ + "GetSessionOptions", + "Get current client session options\n" + "Request Message: GetSessionOptionsRequest\n" + "Response Message: GetSessionOptionsResult\n" + }; +const ActionType ActionType::kCloseSession = + ActionType{ + "CloseSession", + "Explicitly close/invalidate the cookie-specified client session.\n" + "Request Message: CloseSessionRequest\n" + "Response Message: CloseSessionResult\n" + }; bool ActionType::Equals(const ActionType& other) const { return type == other.type && description == other.description; diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 790a2067dd705..592f06860e054 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -184,6 +184,9 @@ struct ARROW_FLIGHT_EXPORT ActionType { static const ActionType kCancelFlightInfo; static const ActionType kRenewFlightEndpoint; + static const ActionType kSetSessionOptions; + static const ActionType kGetSessionOptions; + static const ActionType kCloseSession; }; /// \brief Opaque selection criteria for ListFlights RPC @@ -761,6 +764,175 @@ struct ARROW_FLIGHT_EXPORT CancelFlightInfoRequest { static arrow::Result Deserialize(std::string_view serialized); }; + + + +/// \brief Variant supporting all possible value types for {Set,Get}SessionOptions +using SessionOptionValue = + std::variant>; + +/// \brief The result of setting a session option. +enum class SetSessionOptionResult : int8_t { + kUnspecified, + kOk, + kOkMapped, // PHOXME add remapped key/value status(es) to Proto too + kInvalidResult, + kError +}; + +/// \brief The result of closing a session. +enum class CloseSessionResult : int8_t { + kUnspecified, + kClosed, + kClosing, + kNotClosable +}; + +/// \brief A request to set a set of session options by key/value. +struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsRequest { + std::map session_options; + + std::string ToString() const; + bool Equals(const SetSessionOptionsRequest& other) const; + + friend bool operator==(const SetSessionOptionsRequest& left, + const SetSessionOptionsRequest& right) { + return left.Equals(right); + } + friend bool operator!=(const SetSessionOptionsRequest& left, + const SetSessionOptionsRequest& right)){ + return !(left == right); + } + + /// \brief Serialize this message to its wire-format representation. + arrow::Result SerializeToString() const; + + /// \brief Deserialize this message from its wire-format representation. + static arrow::Result + Deserialize(std::string_view serialized); +}; + +/// \brief The result(s) of setting session option(s). +struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsResult { + std::map results; + + std::string ToString() const; + bool Equals(const SetSessionOptionsResult& other) const; + + friend bool operator==(const SetSessionOptionsResult& left, + const SetSessionOptionsResult& right) { + return left.Equals(right); + } + friend bool operator!=(const SetSessionOptionsResult& left, + const SetSessionOptionsResult& right)){ + return !(left == right); + } + + /// \brief Serialize this message to its wire-format representation. + arrow::Result SerializeToString() const; + + /// \brief Deserialize this message from its wire-format representation. + static arrow::Result + Deserialize(std::string_view serialized); +}; + +/// \brief A request to get current session options. +struct ARROW_FLIGHT_SQL_EXPORT GetSessionOptionsRequest { + std::string ToString() const; + bool Equals(const GetSessionOptionsRequest& other) const; + + friend bool operator==(const GetSessionOptionsRequest& left, + const GetSessionOptionsRequest& right) { + return left.Equals(right); + } + friend bool operator!=(const GetSessionOptionsRequest& left, + const GetSessionOptionsRequest& right)){ + return !(left == right); + } + + /// \brief Serialize this message to its wire-format representation. + arrow::Result SerializeToString() const; + + /// \brief Deserialize this message from its wire-format representation. + static arrow::Result + Deserialize(std::string_view serialized); +}; + +/// \brief The current session options. +struct ARROW_FLIGHT_SQL_EXPORT GetSessionOptionsResult { + std::map session_options; + + std::string ToString() const; + bool Equals(const GetSessionOptionsResult& other) const; + + friend bool operator==(const GetSessionOptionsResult& left, + const GetSessionOptionsResult& right) { + return left.Equals(right); + } + friend bool operator!=(const GetSessionOptionsResult& left, + const GetSessionOptionsResult& right)){ + return !(left == right); + } + + /// \brief Serialize this message to its wire-format representation. + arrow::Result SerializeToString() const; + + /// \brief Deserialize this message from its wire-format representation. + static arrow::Result + Deserialize(std::string_view serialized); +}; + +// PHOXME struct CloseSessionResult (already below??) + +/// \brief A request to close the open client session. +struct ARROW_FLIGHT_SQL_EXPORT CloseSessionRequest { std::string ToString() const; + bool Equals(const CloseSessionRequest& other) const; + + friend bool operator==(const CloseSessionRequest& left, + const CloseSessionRequest& right) { + return left.Equals(right); + } + friend bool operator!=(const CloseSessionRequest& left, + const CloseSessionRequest& right)){ + return !(left == right); + } + + /// \brief Serialize this message to its wire-format representation. + arrow::Result SerializeToString() const; + + /// \brief Deserialize this message from its wire-format representation. + static arrow::Result + Deserialize(std::string_view serialized); +}; + +/// \brief The result of attempting to close the client session. +struct ARROW_FLIGHT_SQL_EXPORT CloseSessionResult { + CloseSessionResult result; + + std::string ToString() const; + bool Equals(const CloseSessionResult& other) const; + + friend bool operator==(const CloseSessionResult& left, + const CloseSessionResult& right) { + return left.Equals(right); + } + friend bool operator!=(const CloseSessionResult& left, + const CloseSessionResult& right)){ + return !(left == right); + } + + /// \brief Serialize this message to its wire-format representation. + arrow::Result SerializeToString() const; + + /// \brief Deserialize this message from its wire-format representation. + static arrow::Result + Deserialize(std::string_view serialized); +} + + + + + /// \brief An iterator to FlightInfo instances returned by ListFlights. class ARROW_FLIGHT_EXPORT FlightListing { public: From 7ede0b3b89dd5562c8494ae12b58662c2c0f7c27 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 30 Oct 2023 09:37:13 -0700 Subject: [PATCH 020/195] WIP: impl *::Deserialize() --- cpp/src/arrow/flight/types.cc | 173 +++++++++++++++++++++++++++++----- cpp/src/arrow/flight/types.h | 48 +++++++++- 2 files changed, 191 insertions(+), 30 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index b06be84912ba1..f73119a0987b9 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -477,22 +477,54 @@ arrow::Result CancelFlightInfoRequest::Deserialize( // PHOXME impl... -std::string SetSessionOptionsRequest::ToString() const { +// PHOXME extend SessionOptionMapToString to support result code enums too +template +static std::string SessionOptionMapToString(std::map) { + // PHOXME replace with operator<< std::stringstream ss; - ss << ""; + ss << '}'; + + return ss.str(); +} +static bool CompareSessionOptionMaps( + const std::map& a, + const std::map& b) { + if (a.session_options.size() != b.session_options.size()) { + return false; + } + for (const auto & [k, v] : a.session_options) { + if (!b.session_options.contains(k)) { + return false; + } + const auto& b_v = b.session_options[k]; + if (v.index() != b_v.index()) { + return false; + } + if (v != b_v) { + return false; + } + } + return true; +} + +// SetSessionOptionsRequest +std::string SetSessionOptionsRequest::ToString() const { + std::stringstream ss;32 + + ss << "(serialized.size())); + if (!pb_request.ParseFromZeroCopyStream(&input)) { + return Status::Invalid("Not a valid SetSessionOptionsRequest"); + } + SetSessionOptionsRequest out; + RETURN_NOT_OK(internal::FromProto(pb_request, &out)); + return out; +} -std::string SetSessionOptionsResult::ToString() const {} +// SetSessionOptionsResult +std::string SetSessionOptionsResult::ToString() const { + // TODO 1/ +} bool SetSessionOptionsResult::Equals(const SetSessionOptionsResult& other) const { - // Simple comparison with fixed types if (results != other.results) { return false; } @@ -530,14 +577,29 @@ SetSessionOptionsResult::SerializeToString() const { return out; } static arrow::Result -SetSessionOptionsResult::Deserialize(std::string_view serialized) {} - - +SetSessionOptionsResult::Deserialize(std::string_view serialized) { + pb::SetSessionOptionsResult pb_result; + if (serialized.size() > static_cast(std::numeric_limits::max())) { + return Status::Invalid( + "Serialized SetSessionOptionsResult size should not exceed 2 GiB"); + } + google::protobuf::io::ArrayInputStream input(serialized.data(), + static_cast(serialized.size())); + if (!pb_result.ParseFromZeroCopyStream(&input)) { + return Status::Invalid("Not a valid SetSessionOptionsResult"); + } + SetSessionOptionsResult out; + RETURN_NOT_OK(internal::FromProto(pb_result, &out)); + return out; +} +// GetSessionOptionsRequest std::string GetSessionOptionsRequest::ToString() const { + return ""; +} +bool GetSessionOptionsRequest::Equals(const GetSessionOptionsRequest& other) const { return true; } -bool GetSessionOptionsRequest::Equals(const GetSessionOptionsRequest& other) const {} arrow::Result GetSessionOptionsRequest::SerializeToString() const { pb::GetSessionOptionsRequest pb_request; @@ -550,16 +612,28 @@ GetSessionOptionsRequest::SerializeToString() const { return out; } static arrow::Result -GetSessionOptionsRequest::Deserialize(std::string_view serialized) {} - - +GetSessionOptionsRequest::Deserialize(std::string_view serialized) { + pb::GetSessionOptionsRequest pb_request; + if (serialized.size() > static_cast(std::numeric_limits::max())) { + return Status::Invalid( + "Serialized GetSessionOptionsRequest size should not exceed 2 GiB"); + } + google::protobuf::io::ArrayInputStream input(serialized.data(), + static_cast(serialized.size())); + if (!pb_request.ParseFromZeroCopyStream(&input)) { + return Status::Invalid("Not a valid GetSessionOptionsRequest"); + } + GetSessionOptionsRequest out; + RETURN_NOT_OK(internal::FromProto(pb_request, &out)); + return out; +} +// GetSessionOptionsResult std::string GetSessionOptionsResult::ToString() const { - // compare map equality including variant types not just value equality + // TODO 2/ (another string method?) } bool GetSessionOptionsResult::Equals(const GetSessionOptionsResult& other) const { - // compare map equality including variant types not just value equality - // PHOXME + return CompareSessionOptionMaps(session_options, other.session_options); } arrow::Result GetSessionOptionsResult::SerializeToString() const { @@ -573,11 +647,27 @@ GetSessionOptionsResult::SerializeToString() const { return out; } static arrow::Result -GetSessionOptionsResult::Deserialize(std::string_view serialized) {} +GetSessionOptionsResult::Deserialize(std::string_view serialized) { + pb::GetSessionOptionsResult pb_result; + if (serialized.size() > static_cast(std::numeric_limits::max())) { + return Status::Invalid( + "Serialized GetSessionOptionsResult size should not exceed 2 GiB"); + } + google::protobuf::io::ArrayInputStream input(serialized.data(), + static_cast(serialized.size())); + if (!pb_result.ParseFromZeroCopyStream(&input)) { + return Status::Invalid("Not a valid GetSessionOptionsResult"); + } + GetSessionOptionsResult out; + RETURN_NOT_OK(internal::FromProto(pb_result, &out)); + return out; +} -std::string CloseSessionRequest::ToString() const {} +std::string CloseSessionRequest::ToString() const { + return ""; +} bool CloseSessionRequest::Equals(const CloseSessionRequest& other) const { return true; } @@ -593,15 +683,32 @@ CloseSessionRequest::SerializeToString() const { return out; } static arrow::Result -CloseSessionRequest::Deserialize(std::string_view serialized) {} +CloseSessionRequest::Deserialize(std::string_view serialized) { + pb::CloseSessionRequest pb_request; + if (serialized.size() > static_cast(std::numeric_limits::max())) { + return Status::Invalid( + "Serialized CloseSessionRequest size should not exceed 2 GiB"); + } + google::protobuf::io::ArrayInputStream input(serialized.data(), + static_cast(serialized.size())); + if (!pb_request.ParseFromZeroCopyStream(&input)) { + return Status::Invalid("Not a valid CloseSessionRequest"); + } + CloseSessionRequest out; + RETURN_NOT_OK(internal::FromProto(pb_request, &out)); + return out; +} -std::string CloseSessionResult::ToString() const {} +std::string CloseSessionResult::ToString() const { + // TODO 3/ +} bool CloseSessionResult::Equals(const CloseSessionResult& other) const { if (result != other.result) { return false; } + return true; } arrow::Result CloseSessionResult::SerializeToString() const { @@ -615,7 +722,21 @@ CloseSessionResult::SerializeToString() const { return out; } static arrow::Result -CloseSessionResult::Deserialize(std::string_view serialized) {} +CloseSessionResult::Deserialize(std::string_view serialized) { + pb::CloseSessionResult pb_result; + if (serialized.size() > static_cast(std::numeric_limits::max())) { + return Status::Invalid( + "Serialized CloseSessionResult size should not exceed 2 GiB"); + } + google::protobuf::io::ArrayInputStream input(serialized.data(), + static_cast(serialized.size())); + if (!pb_result.ParseFromZeroCopyStream(&input)) { + return Status::Invalid("Not a valid CloseSessionResult"); + } + CloseSessionResult out; + RETURN_NOT_OK(internal::FromProto(pb_result, &out)); + return out; +} diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 592f06860e054..fc1782f04df58 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -776,17 +776,57 @@ enum class SetSessionOptionResult : int8_t { kUnspecified, kOk, kOkMapped, // PHOXME add remapped key/value status(es) to Proto too - kInvalidResult, + kInvalidKey, // PHOXME + kInvalidValue, // PHOXME kError }; +std::ostream& operator<<(std::ostream& os, const SetSessionOptionResultValue& r) { + switch (r) { + case SetSessionOptionResult::kUnspecified: + os << "Unspecified"; + break; + case SetSessionOptionResult::kOk: + os << "Ok"; + break; + case SetSessionOptionResult::kOkMapped: + os << "OkMapped"; + break; + case SetSessionOptionResult::kInvalidKey: + os << "InvalidKey"; + break; + case SetSessionOptionResult::kInvalidValue: + os << "InvalidValue"; + break; + case SetSessionOptionResult::kError: + os << "Error"; + break; + } +} /// \brief The result of closing a session. -enum class CloseSessionResult : int8_t { +enum class CloseSessionResultValue : int8_t { kUnspecified, kClosed, kClosing, kNotClosable }; +std::ostream& operator<<(std::ostream& os, const CloseSessionResult& r) { + switch (r) { + case CloseSessionResult::kUnspecified: + os << "Unspecified"; + break; + case CloseSessionResult::kClosed: + os << "Closed"; + break; + case CloseSessionResult::kClosing: + os << "Closing"; + break; + case CloseSessionResult::kNotClosable: + os << "NotClosable"; + break; + } + return os; +} /// \brief A request to set a set of session options by key/value. struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsRequest { @@ -814,7 +854,7 @@ struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsRequest { /// \brief The result(s) of setting session option(s). struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsResult { - std::map results; + std::map results; std::string ToString() const; bool Equals(const SetSessionOptionsResult& other) const; @@ -907,7 +947,7 @@ struct ARROW_FLIGHT_SQL_EXPORT CloseSessionRequest { std::string ToString() con /// \brief The result of attempting to close the client session. struct ARROW_FLIGHT_SQL_EXPORT CloseSessionResult { - CloseSessionResult result; + CloseSessionResultValue result; std::string ToString() const; bool Equals(const CloseSessionResult& other) const; From d07c91ca4a41539955743d55fec980a623562671 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 13:23:43 -0700 Subject: [PATCH 021/195] WIP: ~finish flight/types.cc & serialization_internal.h --- cpp/src/arrow/flight/serialization_internal.h | 24 ++++++++++++++++++ cpp/src/arrow/flight/types.cc | 25 +++++++++++++------ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.h b/cpp/src/arrow/flight/serialization_internal.h index 1ac7de83d1308..170715129525e 100644 --- a/cpp/src/arrow/flight/serialization_internal.h +++ b/cpp/src/arrow/flight/serialization_internal.h @@ -66,6 +66,18 @@ Status FromProto(const pb::CancelFlightInfoRequest& pb_request, CancelFlightInfoRequest* request); Status FromProto(const pb::SchemaResult& pb_result, std::string* result); Status FromProto(const pb::BasicAuth& pb_basic_auth, BasicAuth* info); +Status FromProto(const pb::SetSessionOptionsRequest& pb_request, + SetSessionOptionsRequest* request); +Status FromProto(const pb::SetSessionOptionsResult& pb_result, + SetSessionOptionsResult* result); +Status FromProto(const pb::GetSessionOptionsRequest& pb_request, + GetSessionOptionsRequest* request); +Status FromProto(const pb::GetSessionOptionsResult& pb_result, + GetSessionOptionsResult* result); +Status FromProto(const pb::CloseSessionRequest& pb_request, + CloseSessionRequest* request); +Status FromProto(const pb::CloseSessionResult& pb_result, + CloseSessionResult* result); Status ToProto(const Timestamp& timestamp, google::protobuf::Timestamp* pb_timestamp); Status ToProto(const FlightDescriptor& descr, pb::FlightDescriptor* pb_descr); @@ -85,6 +97,18 @@ Status ToProto(const Criteria& criteria, pb::Criteria* pb_criteria); Status ToProto(const SchemaResult& result, pb::SchemaResult* pb_result); Status ToProto(const Ticket& ticket, pb::Ticket* pb_ticket); Status ToProto(const BasicAuth& basic_auth, pb::BasicAuth* pb_basic_auth); +Status ToProto(const SetSessionOptionsRequest& request, + pb::SetSessionOptionsRequest* pb_request); +Status ToProto(const SetSessionOptionsResult& result, + pb::SetSessionOptionsResult* pb_result); +Status ToProto(const GetSessionOptionsRequest& request, + pb::GetSessionOptionsRequest* pb_request); +Status ToProto(const GetSessionOptionsResult& result, + pb::GetSessionOptionsResult* pb_result); +Status ToProto(const CloseSessionRequest& request, + pb::CloseSessionRequest* pb_request); +Status ToProto(const CloseSessionResult& result, + pb::CloseSessionResult* pb_result); Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out); diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index f73119a0987b9..d964310aa9dc6 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -477,10 +477,9 @@ arrow::Result CancelFlightInfoRequest::Deserialize( // PHOXME impl... -// PHOXME extend SessionOptionMapToString to support result code enums too +// Helper for stringifying maps containing various types template -static std::string SessionOptionMapToString(std::map) { - // PHOXME replace with operator<< +ostream& operator<<(std::map) { std::stringstream ss; ss << '{'; @@ -516,7 +515,7 @@ static bool CompareSessionOptionMaps( // SetSessionOptionsRequest std::string SetSessionOptionsRequest::ToString() const { - std::stringstream ss;32 + std::stringstream ss; ss << ">(); + std::get>(val) + .reserve(pb_opt_val.string_list_value().values_size()); + for (const std::string& s : pb_opt_val.string_list_value().values()) + std::get>(val).push_back(s); + break; + } + return val; +} + +Result ToProto(const SessionOptionValue& val) { + pb::SessionOptionValue pb_val; + std::visit(overloaded{ + [&](std::string v) { pb_val.set_string_value(v); }, + [&](bool v) { pb_val.set_bool_value(v); }, + [&](int32_t v) { pb_val.set_int32_value(v); }, + [&](int64_t v) { pb_val.set_int64_value(v); }, + [&](float v) { pb_val.set_float_value(v); }, + [&](double v) { pb_val.set_double_value(v); }, + [&](std::vector v) { + auto* string_list_value = pb_val.mutable_string_list_value(); + for (const std::string& s : v) + string_list_value->add_values(s); + } + }, opt_value); + return pb_val; +} + // SetSessionOptionsRequest -// FIXME I still need to move the underlying types into types.{h,cc} to be referenced from here -// FIXME as above I still need to write code to convert SessionOptionValues; debatable if a corresponding map is something to break out (probably??) +// FIXME as above I still need to write code to convert SessionOptionValues; debatable if a corresponding map is something to break out (probably??) (-> yes) Status FromProto(const pb::SetSessionOptionsRequest& pb_request, pb::SetSessionOptionsRequest* request) { @@ -397,12 +448,32 @@ Status ToProto(const SetSessionOptionsRequest request, } -// SetSessionOptionsResult +// SetSessionOptionResult NOTE use static_cast here as in other code in this module e.g. CloseSessionResult + +// Note for primitive types T and pb_T may be equivalent, but nested messages to handle e.g. std::variant +// require a separate, possibly distinct template parameter. std::same_as<> may aid implementation of some +// overloads. +template +Status FromProto(const google::protobuf::Map& pb_dict, + std::map* dict) { + // FIXME impl + } + +template +Status ToProto(const std::map& dict, + google::protobuf::Map* pb_dict) { + for (const auto & [key, val] : dict) { + (*pb_dict)[key] = ToProto(val); + } + return Status::OK(); + } // GetSessionOptionsRequest // GetSessionOptionsResult +// CloseSessionRequest + // CloseSessionResult From 9414dc685df4a0a091151caeeed8708453caeba5 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 17:18:41 -0700 Subject: [PATCH 023/195] Impl FromProto(SessionOptionValue...) --- .../arrow/flight/serialization_internal.cc | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 19ffaab6b696f..57cdf431e74a6 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -379,6 +379,12 @@ Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out) { *out = Buffer::FromString(std::move(str_descr)); return Status::OK(); } + + + + + + // ================================================================================================== // // PHOXME I think most of the enum types will just get static_cast<>() as in (I think?) the CancelFlightInfo code...?? // SessionOptionValue @@ -435,6 +441,52 @@ Result ToProto(const SessionOptionValue& val) { return pb_val; } +// map +Status FromProto(const google::protobuf::map pb_map, //PHOXME maybe need to include google/protobuf/map.h ? shouldn't this be brought in by other headers? + std::map* map) { + *map.clear(); + if (pb_map.size() > 0) { + for (auto& [key, pb_val] : pb_map.session_options()) { + SessionOptionValue val; + switch (pb_val.option_value_case()) { + case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: + return Status::Invalid("Unset option_value for name '" + pb_opt_name + "'"); + case pb::SessionOptionValue::kStringValue: + val = pb_val.string_value(); + break; + case pb::SessionOptionValue::kBoolValue: + val = pb_val.bool_value(); + break; + case pb::SessionOptionValue::kInt32Value: + val = pb_val.int32_value(); + break; + case pb::SessionOptionValue::kInt64Value: + val = pb_val.int64_value(); + break; + case pb::SessionOptionValue::kFloatValue: + val = pb_val.float_value(); + break; + case pb::SessionOptionValue::kDoubleValue: + val = pb_val.double_value(); + break; + case pb::SessionOptionValue::kStringListValue: + val.emplace>(); + std::get>(val) + .reserve(pb_val.string_list_value().values_size()); + for (const std::string& s : pb_val.string_list_value().values()) + std::get>(val).push_back(s); + break; + } + result[key] = std::move(val); + } + } + + return Status::OK(); +} + +Status ToProto(const std::map, + google::protobuf::map* pb_map) {} + // SetSessionOptionsRequest // FIXME as above I still need to write code to convert SessionOptionValues; debatable if a corresponding map is something to break out (probably??) (-> yes) @@ -443,12 +495,12 @@ Status FromProto(const pb::SetSessionOptionsRequest& pb_request, } -Status ToProto(const SetSessionOptionsRequest request, +Status ToProto(const SetSessionOptionsRequest& request, pb::SetSessionOptionsRequest* pb_request) { } -// SetSessionOptionResult NOTE use static_cast here as in other code in this module e.g. CloseSessionResult +// SetSessionOptionsResult NOTE use static_cast here as in other code in this module e.g. CloseSessionResult // Note for primitive types T and pb_T may be equivalent, but nested messages to handle e.g. std::variant // require a separate, possibly distinct template parameter. std::same_as<> may aid implementation of some @@ -469,6 +521,7 @@ Status ToProto(const std::map& dict, } // GetSessionOptionsRequest +Status FromProto(const google:protobuf::) // GetSessionOptionsResult @@ -477,6 +530,7 @@ Status ToProto(const std::map& dict, // CloseSessionResult + // ================================================================================================== // } // namespace internal From 7225a5e53d8de6f60c032631db54337c644ff1b3 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 17:58:47 -0700 Subject: [PATCH 024/195] Random WIP checkpoint --- .../arrow/flight/serialization_internal.cc | 64 ++++++------------- 1 file changed, 19 insertions(+), 45 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 57cdf431e74a6..ce069ac50eb08 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -387,10 +387,10 @@ Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out) { // ================================================================================================== // // PHOXME I think most of the enum types will just get static_cast<>() as in (I think?) the CancelFlightInfo code...?? -// SessionOptionValue -Result FromProto(const pb::SessionOptionValue& pb_val) { - SessionOptionValue val; +// SessionOptionValue +Result FromProto(const pb::SessionOptionValue& pb_val + SessionOptionValue* val) { switch (pb_opt_val.option_value_case()) { case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: return Status::Invalid("Unset option_value for name '" + pb_opt_name + "'"); @@ -420,11 +420,11 @@ Result FromProto(const pb::SessionOptionValue& pb_val) { std::get>(val).push_back(s); break; } - return val; + return Status::OK(); } -Result ToProto(const SessionOptionValue& val) { - pb::SessionOptionValue pb_val; +Result ToProto(const SessionOptionValue& val + pb::SessionOptionValue pb_val) { std::visit(overloaded{ [&](std::string v) { pb_val.set_string_value(v); }, [&](bool v) { pb_val.set_bool_value(v); }, @@ -438,54 +438,28 @@ Result ToProto(const SessionOptionValue& val) { string_list_value->add_values(s); } }, opt_value); - return pb_val; + return Status::OK(); } // map Status FromProto(const google::protobuf::map pb_map, //PHOXME maybe need to include google/protobuf/map.h ? shouldn't this be brought in by other headers? std::map* map) { - *map.clear(); - if (pb_map.size() > 0) { - for (auto& [key, pb_val] : pb_map.session_options()) { - SessionOptionValue val; - switch (pb_val.option_value_case()) { - case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: - return Status::Invalid("Unset option_value for name '" + pb_opt_name + "'"); - case pb::SessionOptionValue::kStringValue: - val = pb_val.string_value(); - break; - case pb::SessionOptionValue::kBoolValue: - val = pb_val.bool_value(); - break; - case pb::SessionOptionValue::kInt32Value: - val = pb_val.int32_value(); - break; - case pb::SessionOptionValue::kInt64Value: - val = pb_val.int64_value(); - break; - case pb::SessionOptionValue::kFloatValue: - val = pb_val.float_value(); - break; - case pb::SessionOptionValue::kDoubleValue: - val = pb_val.double_value(); - break; - case pb::SessionOptionValue::kStringListValue: - val.emplace>(); - std::get>(val) - .reserve(pb_val.string_list_value().values_size()); - for (const std::string& s : pb_val.string_list_value().values()) - std::get>(val).push_back(s); - break; - } - result[key] = std::move(val); - } + if (pb_map.size() == 0) { + return Status::OK(); + } + for (auto& [key, pb_val] : pb_map.session_options()) { + RETURN_NOT_OK(FromProto(pb_val, &map[key])); } - return Status::OK(); } -Status ToProto(const std::map, - google::protobuf::map* pb_map) {} +Status ToProto(const std::map map, + google::protobuf::map* pb_map) { + for (const auto & [key, val] : map) { + RETURN_NOT_OK(ToProto(val, &pb_map[key])); + } + return Status::OK(); +} // SetSessionOptionsRequest // FIXME as above I still need to write code to convert SessionOptionValues; debatable if a corresponding map is something to break out (probably??) (-> yes) From e2b4133a51f5fe8623885577c8bda84b63ee7a05 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:24:44 -0700 Subject: [PATCH 025/195] WIP: Finished serialization_internal.cc ? --- .../arrow/flight/serialization_internal.cc | 101 ++++++++++++------ cpp/src/arrow/flight/types.h | 2 +- 2 files changed, 69 insertions(+), 34 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index ce069ac50eb08..aa7f5e4198936 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -380,15 +380,8 @@ Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out) { return Status::OK(); } - - - - - -// ================================================================================================== // -// PHOXME I think most of the enum types will just get static_cast<>() as in (I think?) the CancelFlightInfo code...?? - // SessionOptionValue + Result FromProto(const pb::SessionOptionValue& pb_val SessionOptionValue* val) { switch (pb_opt_val.option_value_case()) { @@ -442,13 +435,14 @@ Result ToProto(const SessionOptionValue& val } // map -Status FromProto(const google::protobuf::map pb_map, //PHOXME maybe need to include google/protobuf/map.h ? shouldn't this be brought in by other headers? + +Status FromProto(const google::protobuf::map pb_map, //PHOXME maybe need to include google/protobuf/map.h ? shouldn't this be brought in by other headers? std::map* map) { if (pb_map.size() == 0) { return Status::OK(); } for (auto& [key, pb_val] : pb_map.session_options()) { - RETURN_NOT_OK(FromProto(pb_val, &map[key])); + RETURN_NOT_OK(FromProto(pb_val, &(*map)[key])); } return Status::OK(); } @@ -462,50 +456,91 @@ Status ToProto(const std::map map, } // SetSessionOptionsRequest -// FIXME as above I still need to write code to convert SessionOptionValues; debatable if a corresponding map is something to break out (probably??) (-> yes) Status FromProto(const pb::SetSessionOptionsRequest& pb_request, pb::SetSessionOptionsRequest* request) { - + RETURN_NOT_OK(FromProto(pb_request.session_options(), &request->session_options)); + return Status::OK(); } Status ToProto(const SetSessionOptionsRequest& request, pb::SetSessionOptionsRequest* pb_request) { - + RETURN_NOT_OK(ToProto(request.session_options, pb_request->mutable_session_options())); + return Status::OK(); } -// SetSessionOptionsResult NOTE use static_cast here as in other code in this module e.g. CloseSessionResult +// SetSessionOptionsResult -// Note for primitive types T and pb_T may be equivalent, but nested messages to handle e.g. std::variant -// require a separate, possibly distinct template parameter. std::same_as<> may aid implementation of some -// overloads. -template -Status FromProto(const google::protobuf::Map& pb_dict, - std::map* dict) { - // FIXME impl - } +Status FromProto(const pb::SetSessionOptionsResult& pb_result, + SetSessionOptionsResult* result) { + for (const auto& [k, pb_v] : pb_result.results()) { + result->results.insert({k, static_cast(pb_v)}); + } + return Status::OK(); +} -template -Status ToProto(const std::map& dict, - google::protobuf::Map* pb_dict) { - for (const auto & [key, val] : dict) { - (*pb_dict)[key] = ToProto(val); - } - return Status::OK(); - } +Statis ToProto(const SetSessionOptionsResult& result, + pb::SetSessionOptionsResult* pb_result) { + auto* pb_results = pb_result->mutable_results(); + for (const auto& [k, v] : result.results) { + pb_results[k] = static_cast(v); + } + return Status::OK(); +} // GetSessionOptionsRequest -Status FromProto(const google:protobuf::) + +Status FromProto(const pb::GetSessionOptionsRequest& pb_request, + GetSessionOptionsRequest* request) { + return Status::OK(); +} + +Status ToProto(const GetSessionOptionsRequest& request, + pb::GetSessionOptionsRequest* pb_request) { + return Status::OK(); +} // GetSessionOptionsResult +Status FromProto(const pb::GetSessionOptionsResult& pb_result, + GetSessionOptionsResult* result) { + RETURN_NOT_OK(FromProto(pb_result.session_options(), &result->session_options)); + return Status::OK; +} + +Status ToProto(const GetSessionOptionsResult& result, + pb::GetSessionOptionsResult* pb_result) { + RETURN_NOT_OK(ToProto(result.session_options, pb_result->mutable_session_options())); + return Status::OK(); +} + // CloseSessionRequest -// CloseSessionResult +Status FromProto(const pb::CloseSessionRequest& pb_request, + CloseSessionRequest* request) { + return Status::OK(); +} + +Status ToProto(const CloseSessionRequest& request, + pb::CloseSessionRequest* pb_request) { + return Status::OK(); +} +// CloseSessionResult +Status FromProto(const pb::CloseSessionResult& pb_result, + CloseSessionResult* result) { + result->result = static_cast(pb_result.status()); + return Status::OK(); +} -// ================================================================================================== // +Status ToProto(const CloseSessionResult& result, + pb::CloseSessionResult* pb_result) { + pb_result->set_result( + static_cast( + result.result)); + return Status::OK(); +} } // namespace internal } // namespace flight diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index fc1782f04df58..b13c75076ae99 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -780,7 +780,7 @@ enum class SetSessionOptionResult : int8_t { kInvalidValue, // PHOXME kError }; -std::ostream& operator<<(std::ostream& os, const SetSessionOptionResultValue& r) { +std::ostream& operator<<(std::ostream& os, const SetSessionOptionResult& r) { switch (r) { case SetSessionOptionResult::kUnspecified: os << "Unspecified"; From 5c855589f65633a2de245181dd9548ec89295067 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:27:50 -0700 Subject: [PATCH 026/195] WIP: Remove 'Action' prefix from Proto messages --- format/Flight.proto | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/format/Flight.proto b/format/Flight.proto index 055d23c5f0812..c3dd212c644ea 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -531,7 +531,7 @@ message PutResult { * * The exiting session is referenced via a cookie header. */ -message ActionCloseSessionRequest { +message CloseSessionRequest { option (experimental) = true; } @@ -540,7 +540,7 @@ message ActionCloseSessionRequest { * * The result should be wrapped in a google.protobuf.Any message. */ -message ActionCloseSessionResult { +message CloseSessionResult { option (experimental) = true; enum CloseSessionResult { @@ -580,13 +580,13 @@ message SessionOptionValue { } } -message ActionSetSessionOptionsRequest { +message SetSessionOptionsRequest { option (experimental) = true; map session_options = 1; } -message ActionSetSessionOptionsResult { +message SetSessionOptionsResult { option (experimental) = true; enum SetSessionOptionResult { @@ -605,11 +605,11 @@ message ActionSetSessionOptionsResult { map results = 1; } -message ActionGetSessionOptionsRequest { +message GetSessionOptionsRequest { option (experimental) = true; } -message ActionGetSessionOptionsResult { +message GetSessionOptionsResult { option (experimental) = true; map session_options = 1; From b5e37ac7236f87d6f5ecd9551bf5e214d164025c Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:31:34 -0700 Subject: [PATCH 027/195] Reduce long Proto nested enum names --- cpp/src/arrow/flight/serialization_internal.cc | 7 ++++--- format/Flight.proto | 8 ++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index aa7f5e4198936..c3bb75621b06e 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -479,11 +479,12 @@ Status FromProto(const pb::SetSessionOptionsResult& pb_result, return Status::OK(); } -Statis ToProto(const SetSessionOptionsResult& result, +Status ToProto(const SetSessionOptionsResult& result, pb::SetSessionOptionsResult* pb_result) { auto* pb_results = pb_result->mutable_results(); for (const auto& [k, v] : result.results) { - pb_results[k] = static_cast(v); + pb_results[k] = + static_cast(v); } return Status::OK(); } @@ -537,7 +538,7 @@ Status FromProto(const pb::CloseSessionResult& pb_result, Status ToProto(const CloseSessionResult& result, pb::CloseSessionResult* pb_result) { pb_result->set_result( - static_cast( + static_cast( result.result)); return Status::OK(); } diff --git a/format/Flight.proto b/format/Flight.proto index c3dd212c644ea..728d6ca0ec1fc 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -543,7 +543,7 @@ message CloseSessionRequest { message CloseSessionResult { option (experimental) = true; - enum CloseSessionResult { + enum Result { // The session close status is unknown. Servers should avoid using // this value (send a NOT_FOUND error if the requested query is // not known). Clients can retry the request. @@ -559,7 +559,7 @@ message CloseSessionResult { CLOSE_RESULT_NOT_CLOSEABLE = 3; } - CloseSessionResult result = 1; + Result result = 1; } message SessionOptionValue { @@ -589,7 +589,7 @@ message SetSessionOptionsRequest { message SetSessionOptionsResult { option (experimental) = true; - enum SetSessionOptionResult { + enum Result { // The status of setting the option is unknown. Servers should avoid using // this value (send a NOT_FOUND error if the requested query is // not known). Clients can retry the request. @@ -602,7 +602,7 @@ message SetSessionOptionsResult { SET_SESSION_OPTION_RESULT_ERROR = 3; } - map results = 1; + map results = 1; } message GetSessionOptionsRequest { From 6e7dff8c152ae3e779f9291c61d6126b5464b207 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:34:14 -0700 Subject: [PATCH 028/195] Indentation etc. --- .../arrow/flight/serialization_internal.cc | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index c3bb75621b06e..58f0a4e829cad 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -386,7 +386,8 @@ Result FromProto(const pb::SessionOptionValue& pb_val SessionOptionValue* val) { switch (pb_opt_val.option_value_case()) { case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: - return Status::Invalid("Unset option_value for name '" + pb_opt_name + "'"); + return Status::Invalid("Unset option_value for name '" + + pb_opt_name + "'"); case pb::SessionOptionValue::kStringValue: val = pb_opt_val.string_value(); break; @@ -436,7 +437,8 @@ Result ToProto(const SessionOptionValue& val // map -Status FromProto(const google::protobuf::map pb_map, //PHOXME maybe need to include google/protobuf/map.h ? shouldn't this be brought in by other headers? +Status FromProto(const google::protobuf::map pb_map, //PHOXME maybe need to include google/protobuf/map.h ? shouldn't this be brought in by other headers? std::map* map) { if (pb_map.size() == 0) { return Status::OK(); @@ -459,13 +461,15 @@ Status ToProto(const std::map map, Status FromProto(const pb::SetSessionOptionsRequest& pb_request, pb::SetSessionOptionsRequest* request) { - RETURN_NOT_OK(FromProto(pb_request.session_options(), &request->session_options)); + RETURN_NOT_OK(FromProto(pb_request.session_options(), + &request->session_options)); return Status::OK(); } Status ToProto(const SetSessionOptionsRequest& request, pb::SetSessionOptionsRequest* pb_request) { - RETURN_NOT_OK(ToProto(request.session_options, pb_request->mutable_session_options())); + RETURN_NOT_OK(ToProto(request.session_options, + pb_request->mutable_session_options())); return Status::OK(); } @@ -483,8 +487,7 @@ Status ToProto(const SetSessionOptionsResult& result, pb::SetSessionOptionsResult* pb_result) { auto* pb_results = pb_result->mutable_results(); for (const auto& [k, v] : result.results) { - pb_results[k] = - static_cast(v); + pb_results[k] = static_cast(v); } return Status::OK(); } @@ -505,13 +508,15 @@ Status ToProto(const GetSessionOptionsRequest& request, Status FromProto(const pb::GetSessionOptionsResult& pb_result, GetSessionOptionsResult* result) { - RETURN_NOT_OK(FromProto(pb_result.session_options(), &result->session_options)); + RETURN_NOT_OK(FromProto(pb_result.session_options(), + &result->session_options)); return Status::OK; } Status ToProto(const GetSessionOptionsResult& result, pb::GetSessionOptionsResult* pb_result) { - RETURN_NOT_OK(ToProto(result.session_options, pb_result->mutable_session_options())); + RETURN_NOT_OK(ToProto(result.session_options, + pb_result->mutable_session_options())); return Status::OK(); } @@ -538,7 +543,7 @@ Status FromProto(const pb::CloseSessionResult& pb_result, Status ToProto(const CloseSessionResult& result, pb::CloseSessionResult* pb_result) { pb_result->set_result( - static_cast( + static_cast( result.result)); return Status::OK(); } From 9d5d01f9ac81adbf36a1c3317d2a95b2865a6b7b Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:36:08 -0700 Subject: [PATCH 029/195] Update to 'Status' enums in Proto --- format/Flight.proto | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/format/Flight.proto b/format/Flight.proto index 728d6ca0ec1fc..9dcf262fc06ca 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -543,7 +543,7 @@ message CloseSessionRequest { message CloseSessionResult { option (experimental) = true; - enum Result { + enum Status { // The session close status is unknown. Servers should avoid using // this value (send a NOT_FOUND error if the requested query is // not known). Clients can retry the request. @@ -559,7 +559,7 @@ message CloseSessionResult { CLOSE_RESULT_NOT_CLOSEABLE = 3; } - Result result = 1; + Status status = 1; } message SessionOptionValue { @@ -589,7 +589,7 @@ message SetSessionOptionsRequest { message SetSessionOptionsResult { option (experimental) = true; - enum Result { + enum Status { // The status of setting the option is unknown. Servers should avoid using // this value (send a NOT_FOUND error if the requested query is // not known). Clients can retry the request. @@ -602,7 +602,7 @@ message SetSessionOptionsResult { SET_SESSION_OPTION_RESULT_ERROR = 3; } - map results = 1; + map statuses = 1; } message GetSessionOptionsRequest { From dea4a824a2608881a33e70688ffe005c70f07d64 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:40:08 -0700 Subject: [PATCH 030/195] WIP: More replacement of Result with Status for enums --- cpp/src/arrow/flight/serialization_internal.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 58f0a4e829cad..4c74240c1111d 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -477,17 +477,17 @@ Status ToProto(const SetSessionOptionsRequest& request, Status FromProto(const pb::SetSessionOptionsResult& pb_result, SetSessionOptionsResult* result) { - for (const auto& [k, pb_v] : pb_result.results()) { - result->results.insert({k, static_cast(pb_v)}); + for (const auto& [k, pb_v] : pb_result.statuses()) { + result->statuses.insert({k, static_cast(pb_v)}); } return Status::OK(); } Status ToProto(const SetSessionOptionsResult& result, pb::SetSessionOptionsResult* pb_result) { - auto* pb_results = pb_result->mutable_results(); - for (const auto& [k, v] : result.results) { - pb_results[k] = static_cast(v); + auto* pb_statuses = pb_result->mutable_statuses(); + for (const auto& [k, v] : result.statuses) { + pb_statuses[k] = static_cast(v); } return Status::OK(); } @@ -536,15 +536,15 @@ Status ToProto(const CloseSessionRequest& request, Status FromProto(const pb::CloseSessionResult& pb_result, CloseSessionResult* result) { - result->result = static_cast(pb_result.status()); + result->status = static_cast(pb_result.status()); return Status::OK(); } Status ToProto(const CloseSessionResult& result, pb::CloseSessionResult* pb_result) { - pb_result->set_result( - static_cast( - result.result)); + pb_result->set_status( + static_cast( + result.status)); return Status::OK(); } From 0620d386c42960a38bf6d6ea2910ceff43c51c92 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:42:04 -0700 Subject: [PATCH 031/195] WIP: Even more replacement of Result with Status for enums --- cpp/src/arrow/flight/types.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index b13c75076ae99..06c7466a9f2d2 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -772,7 +772,7 @@ using SessionOptionValue = std::variant>; /// \brief The result of setting a session option. -enum class SetSessionOptionResult : int8_t { +enum class SetSessionOptionStatus : int8_t { kUnspecified, kOk, kOkMapped, // PHOXME add remapped key/value status(es) to Proto too @@ -804,7 +804,7 @@ std::ostream& operator<<(std::ostream& os, const SetSessionOptionResult& r) { } /// \brief The result of closing a session. -enum class CloseSessionResultValue : int8_t { +enum class CloseSessionStatus : int8_t { kUnspecified, kClosed, kClosing, @@ -854,7 +854,7 @@ struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsRequest { /// \brief The result(s) of setting session option(s). struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsResult { - std::map results; + std::map statuses; std::string ToString() const; bool Equals(const SetSessionOptionsResult& other) const; @@ -947,7 +947,7 @@ struct ARROW_FLIGHT_SQL_EXPORT CloseSessionRequest { std::string ToString() con /// \brief The result of attempting to close the client session. struct ARROW_FLIGHT_SQL_EXPORT CloseSessionResult { - CloseSessionResultValue result; + CloseSessionStatus status; std::string ToString() const; bool Equals(const CloseSessionResult& other) const; From 15f5bf7c9e983c254350a14acc98298b68fef1d6 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:45:13 -0700 Subject: [PATCH 032/195] WIP: Even MORE replacement of Result with Status for enums --- cpp/src/arrow/flight/types.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index d964310aa9dc6..89020ad81308d 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -558,12 +558,12 @@ SetSessionOptionsRequest::Deserialize(std::string_view serialized) { std::string SetSessionOptionsResult::ToString() const { std::stringstream ss; - ss << ""; } + bool GetSessionOptionsRequest::Equals(const GetSessionOptionsRequest& other) const { return true; } + arrow::Result GetSessionOptionsRequest::SerializeToString() const { pb::GetSessionOptionsRequest pb_request; @@ -614,7 +621,8 @@ GetSessionOptionsRequest::SerializeToString() const { } return out; } -static arrow::Result + +arrow::Result GetSessionOptionsRequest::Deserialize(std::string_view serialized) { pb::GetSessionOptionsRequest pb_request; if (serialized.size() > static_cast(std::numeric_limits::max())) { @@ -632,6 +640,7 @@ GetSessionOptionsRequest::Deserialize(std::string_view serialized) { } // GetSessionOptionsResult + std::string GetSessionOptionsResult::ToString() const { std::stringstream ss; @@ -639,9 +648,11 @@ std::string GetSessionOptionsResult::ToString() const { return ss.str(); } + bool GetSessionOptionsResult::Equals(const GetSessionOptionsResult& other) const { return CompareSessionOptionMaps(session_options, other.session_options); } + arrow::Result GetSessionOptionsResult::SerializeToString() const { pb::GetSessionOptionsResult pb_result; @@ -653,7 +664,8 @@ GetSessionOptionsResult::SerializeToString() const { } return out; } -static arrow::Result + +arrow::Result GetSessionOptionsResult::Deserialize(std::string_view serialized) { pb::GetSessionOptionsResult pb_result; if (serialized.size() > static_cast(std::numeric_limits::max())) { @@ -670,14 +682,16 @@ GetSessionOptionsResult::Deserialize(std::string_view serialized) { return out; } - +// CloseSessionRequest std::string CloseSessionRequest::ToString() const { return ""; } + bool CloseSessionRequest::Equals(const CloseSessionRequest& other) const { return true; } + arrow::Result CloseSessionRequest::SerializeToString() const { pb::CloseSessionRequest pb_request; @@ -689,7 +703,8 @@ CloseSessionRequest::SerializeToString() const { } return out; } -static arrow::Result + +arrow::Result CloseSessionRequest::Deserialize(std::string_view serialized) { pb::CloseSessionRequest pb_request; if (serialized.size() > static_cast(std::numeric_limits::max())) { @@ -706,7 +721,7 @@ CloseSessionRequest::Deserialize(std::string_view serialized) { return out; } - +// CloseSessionResult std::string CloseSessionResult::ToString() const { std::stringstream ss; @@ -715,12 +730,14 @@ std::string CloseSessionResult::ToString() const { return ss.str(); } + bool CloseSessionResult::Equals(const CloseSessionResult& other) const { if (status != other.status) { return false; } return true; } + arrow::Result CloseSessionResult::SerializeToString() const { pb::CloseSessionResult pb_result; @@ -732,7 +749,8 @@ CloseSessionResult::SerializeToString() const { } return out; } -static arrow::Result + +arrow::Result CloseSessionResult::Deserialize(std::string_view serialized) { pb::CloseSessionResult pb_result; if (serialized.size() > static_cast(std::numeric_limits::max())) { @@ -749,10 +767,6 @@ CloseSessionResult::Deserialize(std::string_view serialized) { return out; } - - - - Location::Location() { uri_ = std::make_shared(); } arrow::Result Location::Parse(const std::string& uri_string) { From 433d9bc56ee46b76de4cb88731cadc9016deef1d Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:52:30 -0700 Subject: [PATCH 034/195] Typos --- cpp/src/arrow/flight/serialization_internal.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 4c74240c1111d..5fd0e181d667b 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -382,7 +382,7 @@ Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out) { // SessionOptionValue -Result FromProto(const pb::SessionOptionValue& pb_val +Status FromProto(const pb::SessionOptionValue& pb_val SessionOptionValue* val) { switch (pb_opt_val.option_value_case()) { case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: @@ -417,7 +417,7 @@ Result FromProto(const pb::SessionOptionValue& pb_val return Status::OK(); } -Result ToProto(const SessionOptionValue& val +Status ToProto(const SessionOptionValue& val pb::SessionOptionValue pb_val) { std::visit(overloaded{ [&](std::string v) { pb_val.set_string_value(v); }, From e9e796a0a269bda92672924c6c5e7c26d837d6ce Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 19:58:21 -0700 Subject: [PATCH 035/195] Add new SetSessionOption statuses to Proto --- cpp/src/arrow/flight/types.h | 13 ++----------- format/Flight.proto | 8 ++++++-- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 06c7466a9f2d2..2bdc287098525 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -764,9 +764,6 @@ struct ARROW_FLIGHT_EXPORT CancelFlightInfoRequest { static arrow::Result Deserialize(std::string_view serialized); }; - - - /// \brief Variant supporting all possible value types for {Set,Get}SessionOptions using SessionOptionValue = std::variant>; @@ -791,8 +788,8 @@ std::ostream& operator<<(std::ostream& os, const SetSessionOptionResult& r) { case SetSessionOptionResult::kOkMapped: os << "OkMapped"; break; - case SetSessionOptionResult::kInvalidKey: - os << "InvalidKey"; + case SetSessionOptionResult::kInvalidName: + os << "InvalidName"; break; case SetSessionOptionResult::kInvalidValue: os << "InvalidValue"; @@ -922,8 +919,6 @@ struct ARROW_FLIGHT_SQL_EXPORT GetSessionOptionsResult { Deserialize(std::string_view serialized); }; -// PHOXME struct CloseSessionResult (already below??) - /// \brief A request to close the open client session. struct ARROW_FLIGHT_SQL_EXPORT CloseSessionRequest { std::string ToString() const; bool Equals(const CloseSessionRequest& other) const; @@ -969,10 +964,6 @@ struct ARROW_FLIGHT_SQL_EXPORT CloseSessionResult { Deserialize(std::string_view serialized); } - - - - /// \brief An iterator to FlightInfo instances returned by ListFlights. class ARROW_FLIGHT_EXPORT FlightListing { public: diff --git a/format/Flight.proto b/format/Flight.proto index 9dcf262fc06ca..99e1a1671259c 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -596,10 +596,14 @@ message SetSessionOptionsResult { SET_SESSION_OPTION_RESULT_UNSPECIFIED = 0; // The session option setting completed successfully. SET_SESSION_OPTION_RESULT_OK = 1; + // The given session option name was an alias for another option name. + SET_SESSION_OPTION_RESULT_OK_MAPPED = 2; + // The given session option name is invalid. + SET_SESSION_OPTION_RESULT_INVALID_NAME = 3; // The session cannot be set to the given value. - SET_SESSION_OPTION_RESULT_INVALID_VALUE = 2; + SET_SESSION_OPTION_RESULT_INVALID_VALUE = 4; // The session cannot be set. - SET_SESSION_OPTION_RESULT_ERROR = 3; + SET_SESSION_OPTION_RESULT_ERROR = 5; } map statuses = 1; From f8d0e720042f26aee26dc10daa81f24d37dafa15 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 31 Oct 2023 20:13:12 -0700 Subject: [PATCH 036/195] Fixup flight/client.* --- cpp/src/arrow/flight/client.cc | 171 +-------------------------------- cpp/src/arrow/flight/client.h | 22 +++++ 2 files changed, 25 insertions(+), 168 deletions(-) diff --git a/cpp/src/arrow/flight/client.cc b/cpp/src/arrow/flight/client.cc index e965e2b8e6e7f..e4df782a017f8 100644 --- a/cpp/src/arrow/flight/client.cc +++ b/cpp/src/arrow/flight/client.cc @@ -713,27 +713,6 @@ arrow::Result FlightClient::DoExchange( return result; } -// PHOXME implement these... -arrow::Result FlightClient::SetSessionOptions( - const FlightCallOptions& options, const SetSessionOptionsRequest& request) { - RETURN_NOT_OK(CheckOpen()); - /* - */ -} - -arrow::Result FlightClient::GetSessionOptions( - const FlightCallOptions& options) { - RETURN_NOT_OK(CheckOpen()); - /* - */ -} - -arrow::Result<> FlightClient::CloseSession(const FlightCallOptions& options) { - RETURN_NOT_OK(CheckOpen()); - /* - */ -} - ::arrow::Result FlightClient::SetSessionOptions( const FlightCallOptions& options, @@ -748,68 +727,7 @@ FlightClient::SetSessionOptions( CloseSessionResult::Deserialize( std::string_view(*result->body))); ARROW_RETURN_NOT_OK(stream->Drain()); - return std::move(set_session_options_result); /* PHOXME: take anything from here then delete this code... - pb::SetSessionOptionsRequest request; - auto* options_map = request.mutable_session_options(); - - for (const auto & [name, opt_value] : session_options) { - pb::SessionOptionValue pb_opt_value; - - if (opt_value.index() == std::variant_npos) - return Status::Invalid("Undefined SessionOptionValue type "); - - std::visit(overloaded{ - // TODO move this somewhere common that can have Proto-involved code - [&](std::string v) { pb_opt_value.set_string_value(v); }, - [&](bool v) { pb_opt_value.set_bool_value(v); }, - [&](int32_t v) { pb_opt_value.set_int32_value(v); }, - [&](int64_t v) { pb_opt_value.set_int64_value(v); }, - [&](float v) { pb_opt_value.set_float_value(v); }, - [&](double v) { pb_opt_value.set_double_value(v); }, - [&](std::vector v) { - auto* string_list_value = pb_opt_value.mutable_string_list_value(); - for (const std::string& s : v) - string_list_value->add_values(s); - } - }, opt_value); - (*options_map)[name] = std::move(pb_opt_value); - } - - - - std::unique_ptr results; - ARROW_ASSIGN_OR_RAISE(auto action, PackAction("SetSessionOptions", request)); - ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); - - - - pb::SetSessionOptionsResult pb_result; - ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); - ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); - std::map result; - - for (const auto & [result_key, result_value] : pb_result.results()) { - switch (result_value) { - case pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED: - result[result_key] = SetSessionOptionResult::kUnspecified; - break; - case pb::SetSessionOptionsResult - ::SET_SESSION_OPTION_RESULT_OK: - result[result_key] = SetSessionOptionResult::kOk; - break; - case pb::SetSessionOptionsResult - ::SET_SESSION_OPTION_RESULT_INVALID_VALUE: - result[result_key] = SetSessionOptionResult::kInvalidResult; - break; - case pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR: - result[result_key] = SetSessionOptionResult::kError; - break; - default: - return Status::IOError("Invalid SetSessionOptionResult value for key " - + result_key); - } - } - */ + return set_session_options_result; } ::arrow::Result @@ -825,57 +743,7 @@ FlightClient::GetSessionOptions ( CloseSessionResult::Deserialize( std::string_view(*result->body))); ARROW_RETURN_NOT_OK(stream->Drain()); - return std::move(get_session_options_result); - /* PHOXME: take anything from here then delete this code... - pb::GetSessionOptionsRequest request; - - std::unique_ptr results; - ARROW_ASSIGN_OR_RAISE(auto action, PackAction("GetSessionOptions", request)); - ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); - - pb::GetSessionOptionsResult pb_result; - ARROW_RETURN_NOT_OK(ReadResult(results.get(), &pb_result)); - ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); - - std::map result; - if (pb_result.session_options_size() > 0) { - for (auto& [pb_opt_name, pb_opt_val] : pb_result.session_options()) { - SessionOptionValue val; - switch (pb_opt_val.option_value_case()) { - case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: - return Status::Invalid("Unset option_value for name '" + pb_opt_name + "'"); - case pb::SessionOptionValue::kStringValue: - val = pb_opt_val.string_value(); - break; - case pb::SessionOptionValue::kBoolValue: - val = pb_opt_val.bool_value(); - break; - case pb::SessionOptionValue::kInt32Value: - val = pb_opt_val.int32_value(); - break; - case pb::SessionOptionValue::kInt64Value: - val = pb_opt_val.int64_value(); - break; - case pb::SessionOptionValue::kFloatValue: - val = pb_opt_val.float_value(); - break; - case pb::SessionOptionValue::kDoubleValue: - val = pb_opt_val.double_value(); - break; - case pb::SessionOptionValue::kStringListValue: - val.emplace>(); - std::get>(val) - .reserve(pb_opt_val.string_list_value().values_size()); - for (const std::string& s : pb_opt_val.string_list_value().values()) - std::get>(val).push_back(s); - break; - } - result[pb_opt_name] = std::move(val); - } - } - - return result; - */ + return get_session_options_result; } ::arrow::Result FlightClient::CloseSession( @@ -889,42 +757,9 @@ ::arrow::Result FlightClient::CloseSession( CloseSessionResult::Deserialize( std::string_view(*result->body))); ARROW_RETURN_NOT_OK(stream->Drain()); - return std::move(close_session_result); + return close_session_result; } - -/* PHOXME: take anything from here then delete this code... - pb::CloseSessionRequest request; - - std::unique_ptr results; - ARROW_ASSIGN_OR_RAISE(auto action, PackAction("CloseSession", request)); - ARROW_RETURN_NOT_OK(DoAction(options, action, &results)); - - pb::ActionCloseSessionResult result; - ARROW_RETURN_NOT_OK(ReadResult(results.get(), &result)); - ARROW_RETURN_NOT_OK(DrainResultStream(results.get())); - switch (result.result()) { - case pb::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED: - return CloseSessionResult::kUnspecified; - case pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSED: - return CloseSessionResult::kClosed; - case pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSING: - return CloseSessionResult::kClosing; - case pb::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE: - return CloseSessionResult::kNotClosable; - default: - break; - } - - return Status::IOError("Server returned unknown result ", result.result()); */ - -// /PHOXME - - - - - - Status FlightClient::Close() { if (!closed_) { closed_ = true; diff --git a/cpp/src/arrow/flight/client.h b/cpp/src/arrow/flight/client.h index 1df71d2029f74..66ba797a0f25e 100644 --- a/cpp/src/arrow/flight/client.h +++ b/cpp/src/arrow/flight/client.h @@ -383,6 +383,28 @@ class ARROW_FLIGHT_EXPORT FlightClient { return DoExchange({}, descriptor); } +/// \\brief Set server session option(s) by key/value. Sessions are generally +/// persisted via HTTP cookies. +/// \param[in] options Per-RPC options +/// \param[in] session_options The server session options to set +::arrow::Result +FlightClient::SetSessionOptions( + const FlightCallOptions& options, + const std::map& session_options); + +/// \\brief Get the current server session options. The session is generally +/// accessed via an HTTP cookie. +/// \param[in] options Per-RPC options +::arrow::Result +FlightClient::GetSessionOptions ( + const FlightCallOptions& options); + +/// \\brief Close/invalidate the current server session. The session is generally +/// accessed via an HTTP cookie. +/// \param[in] options Per-RPC options +::arrow::Result FlightClient::CloseSession( + const FlightCallOptions& options); + /// \brief Explicitly shut down and clean up the client. /// /// For backwards compatibility, this will be implicitly called by From 001ab4aa51e918a10d8be6960f463f731df076fb Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 1 Nov 2023 12:00:04 -0700 Subject: [PATCH 037/195] Fix name change + remove temporary comments --- cpp/src/arrow/flight/types.cc | 2 +- cpp/src/arrow/flight/types.h | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 6d35027387baf..b0521e4ca36e1 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -481,7 +481,7 @@ ostream& operator<<(std::map) { ss << '{'; std::string sep = ""; for (const auto& [k, v] : session_options) { - std::cout << sep << '[' << k << "]: '" << v << "', "; // PHOXME v.ToString() not implemented yet + std::cout << sep << '[' << k << "]: '" << v << "', "; sep = ", "; } ss << '}'; diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 2bdc287098525..c279e66c4f8c2 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -772,29 +772,29 @@ using SessionOptionValue = enum class SetSessionOptionStatus : int8_t { kUnspecified, kOk, - kOkMapped, // PHOXME add remapped key/value status(es) to Proto too - kInvalidKey, // PHOXME - kInvalidValue, // PHOXME + kOkMapped, + kInvalidKey, + kInvalidValue, kError }; -std::ostream& operator<<(std::ostream& os, const SetSessionOptionResult& r) { +std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& r) { switch (r) { - case SetSessionOptionResult::kUnspecified: + case SetSessionOptionStatus::kUnspecified: os << "Unspecified"; break; - case SetSessionOptionResult::kOk: + case SetSessionOptionStatus::kOk: os << "Ok"; break; - case SetSessionOptionResult::kOkMapped: + case SetSessionOptionStatus::kOkMapped: os << "OkMapped"; break; - case SetSessionOptionResult::kInvalidName: + case SetSessionOptionStatus::kInvalidName: os << "InvalidName"; break; - case SetSessionOptionResult::kInvalidValue: + case SetSessionOptionStatus::kInvalidValue: os << "InvalidValue"; break; - case SetSessionOptionResult::kError: + case SetSessionOptionStatus::kError: os << "Error"; break; } @@ -807,18 +807,18 @@ enum class CloseSessionStatus : int8_t { kClosing, kNotClosable }; -std::ostream& operator<<(std::ostream& os, const CloseSessionResult& r) { +std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& r) { switch (r) { - case CloseSessionResult::kUnspecified: + case CloseSessionStatus::kUnspecified: os << "Unspecified"; break; - case CloseSessionResult::kClosed: + case CloseSessionStatus::kClosed: os << "Closed"; break; - case CloseSessionResult::kClosing: + case CloseSessionStatus::kClosing: os << "Closing"; break; - case CloseSessionResult::kNotClosable: + case CloseSessionStatus::kNotClosable: os << "NotClosable"; break; } From 071c42fd5f7a54e5463d6cbfaec63f647f26c32f Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 1 Nov 2023 12:06:45 -0700 Subject: [PATCH 038/195] Move lambda overload helpers around & other cleanup --- .../arrow/flight/serialization_internal.cc | 6 ++++ cpp/src/arrow/flight/sql/client.cc | 7 ---- cpp/src/arrow/flight/sql/server.cc | 34 ++++++++++++------- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 5fd0e181d667b..78399b9681bc9 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -27,6 +27,12 @@ #include "arrow/result.h" #include "arrow/status.h" +// Lambda helper & CTAD +template +struct overloaded : Ts... { using Ts::operator()...; }; +template // CTAD will not be needed for >=C++20 +overloaded(Ts...) -> overloaded; + namespace arrow { namespace flight { namespace internal { diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index c3f141bc1e7e6..9885ddc939996 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -31,13 +31,6 @@ #include "arrow/result.h" #include "arrow/util/logging.h" -// Lambda helper & CTAD -template -struct overloaded : Ts... { using Ts::operator()...; }; -template // CTAD will not be needed for >=C++20 -overloaded(Ts...) -> overloaded; - -namespace pb = arrow::flight::protocol; namespace flight_sql_pb = arrow::flight::protocol::sql; namespace arrow { diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index a9703bc314ee6..31cebd9efd474 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -33,12 +33,6 @@ #include "arrow/type.h" #include "arrow/util/checked_cast.h" -// Lambda helper & CTAD -template -struct overloaded : Ts... { using Ts::operator()...; }; -template // CTAD will not be needed for >=C++20 -overloaded(Ts...) -> overloaded; - #define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \ COMMAND.has_##PROPERTY() ? std::make_optional(COMMAND.PROPERTY()) : std::nullopt @@ -517,8 +511,14 @@ arrow::Result PackActionResult(ActionCreatePreparedStatementResult resul return PackActionResult(pb_result); } + +// PHOXME remove code from 3 impls after serde stuff is written and/or *moved* arrow::Result PackActionResult(SetSessionOptionsResult result) { - pb::SetSessionOptionsResult pb_result; + ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString()); + return Result(Buffer::FromString(std::move(serialized)); + + + /* pb::SetSessionOptionsResult pb_result; auto* pb_results_map = pb_result.mutable_results(); for (const auto& [opt_name, res] : result.results) { pb::ActionSetSessionOptionsResult_SetSessionOptionResult val; @@ -538,11 +538,15 @@ arrow::Result PackActionResult(SetSessionOptionsResult result) { } (*pb_results_map)[opt_name] = val; } - return PackActionResult(pb_result); + return PackActionResult(pb_result); */ } arrow::Result PackActionResult(GetSessionOptionsResult result) { - pb::GetSessionOptionsResult pb_result; + ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString()); + return Result(Buffer::FromString(std::move(serialized)); + + + /* pb::GetSessionOptionsResult pb_result; auto* pb_results = pb_result.mutable_session_options(); for (const auto& [name, opt_value] : result.session_options) { pb::SessionOptionValue pb_opt_value; @@ -567,11 +571,15 @@ arrow::Result PackActionResult(GetSessionOptionsResult result) { (*pb_results)[name] = std::move(pb_opt_value); } - return PackActionResult(pb_result); + return PackActionResult(pb_result); */ } arrow::Result PackActionResult(CloseSessionResult result) { - pb::ActionCloseSessionResult pb_result; + ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString()); + return Result(Buffer::FromString(std::move(serialized)); + + + /* pb::ActionCloseSessionResult pb_result; switch (result) { case CloseSessionResult::kUnspecified: pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED); @@ -586,9 +594,11 @@ arrow::Result PackActionResult(CloseSessionResult result) { pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE); break; } - return PackActionResult(pb_result); + return PackActionResult(pb_result);*/ } +// /PHOXME + } // namespace arrow::Result StatementQueryTicket::Deserialize( From abfbec6fc74013cf3cc928218931b49c09db71be Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 1 Nov 2023 19:16:54 -0700 Subject: [PATCH 039/195] Fixed all but 1 build error --- cpp/src/arrow/flight/client.cc | 12 +- cpp/src/arrow/flight/client.h | 16 +- .../arrow/flight/serialization_internal.cc | 69 ++++---- cpp/src/arrow/flight/sql/client.h | 16 +- cpp/src/arrow/flight/sql/server.cc | 150 +----------------- .../flight/sql/server_session_middleware.cc | 6 +- .../flight/sql/server_session_middleware.h | 6 +- cpp/src/arrow/flight/types.cc | 50 +++--- cpp/src/arrow/flight/types.h | 33 ++-- format/Flight.proto | 1 + 10 files changed, 119 insertions(+), 240 deletions(-) diff --git a/cpp/src/arrow/flight/client.cc b/cpp/src/arrow/flight/client.cc index e4df782a017f8..1e5a843d19d66 100644 --- a/cpp/src/arrow/flight/client.cc +++ b/cpp/src/arrow/flight/client.cc @@ -716,7 +716,7 @@ arrow::Result FlightClient::DoExchange( ::arrow::Result FlightClient::SetSessionOptions( const FlightCallOptions& options, - const std::map& session_options) { + const SetSessionOptionsRequest& request) { RETURN_NOT_OK(CheckOpen()); RETURN_NOT_OK(CheckOpen()); ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); @@ -724,7 +724,7 @@ FlightClient::SetSessionOptions( ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); ARROW_ASSIGN_OR_RAISE(auto result, stream->Next()); ARROW_ASSIGN_OR_RAISE(auto set_session_options_result, - CloseSessionResult::Deserialize( + SetSessionOptionsResult::Deserialize( std::string_view(*result->body))); ARROW_RETURN_NOT_OK(stream->Drain()); return set_session_options_result; @@ -732,7 +732,8 @@ FlightClient::SetSessionOptions( ::arrow::Result FlightClient::GetSessionOptions ( - const FlightCallOptions& options) { + const FlightCallOptions& options, + const GetSessionOptionsRequest& request) { RETURN_NOT_OK(CheckOpen()); RETURN_NOT_OK(CheckOpen()); ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); @@ -740,14 +741,15 @@ FlightClient::GetSessionOptions ( ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); ARROW_ASSIGN_OR_RAISE(auto result, stream->Next()); ARROW_ASSIGN_OR_RAISE(auto get_session_options_result, - CloseSessionResult::Deserialize( + GetSessionOptionsResult::Deserialize( std::string_view(*result->body))); ARROW_RETURN_NOT_OK(stream->Drain()); return get_session_options_result; } ::arrow::Result FlightClient::CloseSession( - const FlightCallOptions& options) { + const FlightCallOptions& options, + const CloseSessionRequest& request) { RETURN_NOT_OK(CheckOpen()); ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); Action action{ActionType::kCloseSession.type, Buffer::FromString(body)}; diff --git a/cpp/src/arrow/flight/client.h b/cpp/src/arrow/flight/client.h index 66ba797a0f25e..68c9140d9a51c 100644 --- a/cpp/src/arrow/flight/client.h +++ b/cpp/src/arrow/flight/client.h @@ -387,23 +387,23 @@ class ARROW_FLIGHT_EXPORT FlightClient { /// persisted via HTTP cookies. /// \param[in] options Per-RPC options /// \param[in] session_options The server session options to set -::arrow::Result -FlightClient::SetSessionOptions( +::arrow::Result SetSessionOptions( const FlightCallOptions& options, - const std::map& session_options); + const SetSessionOptionsRequest& session_options); /// \\brief Get the current server session options. The session is generally /// accessed via an HTTP cookie. /// \param[in] options Per-RPC options -::arrow::Result -FlightClient::GetSessionOptions ( - const FlightCallOptions& options); +::arrow::Result GetSessionOptions ( + const FlightCallOptions& options, + const GetSessionOptionsRequest& request); /// \\brief Close/invalidate the current server session. The session is generally /// accessed via an HTTP cookie. /// \param[in] options Per-RPC options -::arrow::Result FlightClient::CloseSession( - const FlightCallOptions& options); +::arrow::Result CloseSession( + const FlightCallOptions& options, + const CloseSessionRequest& request); /// \brief Explicitly shut down and clean up the client. /// diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 78399b9681bc9..625d0c0a85a58 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -388,77 +388,76 @@ Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out) { // SessionOptionValue -Status FromProto(const pb::SessionOptionValue& pb_val - SessionOptionValue* val) { - switch (pb_opt_val.option_value_case()) { +Status FromProto(const pb::SessionOptionValue& pb_val, + SessionOptionValue* val) { + switch (pb_val.option_value_case()) { case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: - return Status::Invalid("Unset option_value for name '" + - pb_opt_name + "'"); + return Status::Invalid("Unset SessionOptionValue found"); case pb::SessionOptionValue::kStringValue: - val = pb_opt_val.string_value(); + *val = pb_val.string_value(); break; case pb::SessionOptionValue::kBoolValue: - val = pb_opt_val.bool_value(); + *val = pb_val.bool_value(); break; case pb::SessionOptionValue::kInt32Value: - val = pb_opt_val.int32_value(); + *val = pb_val.int32_value(); break; case pb::SessionOptionValue::kInt64Value: - val = pb_opt_val.int64_value(); + *val = pb_val.int64_value(); break; case pb::SessionOptionValue::kFloatValue: - val = pb_opt_val.float_value(); + *val = pb_val.float_value(); break; case pb::SessionOptionValue::kDoubleValue: - val = pb_opt_val.double_value(); + *val = pb_val.double_value(); break; case pb::SessionOptionValue::kStringListValue: - val.emplace>(); - std::get>(val) - .reserve(pb_opt_val.string_list_value().values_size()); - for (const std::string& s : pb_opt_val.string_list_value().values()) - std::get>(val).push_back(s); + (*val).emplace>(); + std::get>(*val) + .reserve(pb_val.string_list_value().values_size()); + for (const std::string& s : pb_val.string_list_value().values()) + std::get>(*val).push_back(s); break; } return Status::OK(); } -Status ToProto(const SessionOptionValue& val - pb::SessionOptionValue pb_val) { +Status ToProto(const SessionOptionValue& val, + pb::SessionOptionValue* pb_val) { std::visit(overloaded{ - [&](std::string v) { pb_val.set_string_value(v); }, - [&](bool v) { pb_val.set_bool_value(v); }, - [&](int32_t v) { pb_val.set_int32_value(v); }, - [&](int64_t v) { pb_val.set_int64_value(v); }, - [&](float v) { pb_val.set_float_value(v); }, - [&](double v) { pb_val.set_double_value(v); }, + [&](std::string v) { pb_val->set_string_value(v); }, + [&](bool v) { pb_val->set_bool_value(v); }, + [&](int32_t v) { pb_val->set_int32_value(v); }, + [&](int64_t v) { pb_val->set_int64_value(v); }, + [&](float v) { pb_val->set_float_value(v); }, + [&](double v) { pb_val->set_double_value(v); }, [&](std::vector v) { - auto* string_list_value = pb_val.mutable_string_list_value(); + auto* string_list_value = pb_val->mutable_string_list_value(); for (const std::string& s : v) string_list_value->add_values(s); } - }, opt_value); + }, val); return Status::OK(); } // map -Status FromProto(const google::protobuf::map pb_map, //PHOXME maybe need to include google/protobuf/map.h ? shouldn't this be brought in by other headers? +Status FromProto(const google::protobuf::Map& pb_map, //PHOXME maybe need to include google/protobuf/map.h ? shouldn't this be brought in by other headers? std::map* map) { if (pb_map.size() == 0) { return Status::OK(); } - for (auto& [key, pb_val] : pb_map.session_options()) { + for (auto& [key, pb_val] : pb_map) { RETURN_NOT_OK(FromProto(pb_val, &(*map)[key])); } return Status::OK(); } -Status ToProto(const std::map map, - google::protobuf::map* pb_map) { +Status ToProto(const std::map& map, + google::protobuf::Map* pb_map) { for (const auto & [key, val] : map) { - RETURN_NOT_OK(ToProto(val, &pb_map[key])); + RETURN_NOT_OK(ToProto(val, &(*pb_map)[key])); } return Status::OK(); } @@ -466,7 +465,7 @@ Status ToProto(const std::map map, // SetSessionOptionsRequest Status FromProto(const pb::SetSessionOptionsRequest& pb_request, - pb::SetSessionOptionsRequest* request) { + SetSessionOptionsRequest* request) { RETURN_NOT_OK(FromProto(pb_request.session_options(), &request->session_options)); return Status::OK(); @@ -493,7 +492,7 @@ Status ToProto(const SetSessionOptionsResult& result, pb::SetSessionOptionsResult* pb_result) { auto* pb_statuses = pb_result->mutable_statuses(); for (const auto& [k, v] : result.statuses) { - pb_statuses[k] = static_cast(v); + (*pb_statuses)[k] = static_cast(v); } return Status::OK(); } @@ -516,7 +515,7 @@ Status FromProto(const pb::GetSessionOptionsResult& pb_result, GetSessionOptionsResult* result) { RETURN_NOT_OK(FromProto(pb_result.session_options(), &result->session_options)); - return Status::OK; + return Status::OK(); } Status ToProto(const GetSessionOptionsResult& result, diff --git a/cpp/src/arrow/flight/sql/client.h b/cpp/src/arrow/flight/sql/client.h index f16ee47cbe5fa..5ad21a0162ee5 100644 --- a/cpp/src/arrow/flight/sql/client.h +++ b/cpp/src/arrow/flight/sql/client.h @@ -354,26 +354,28 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlClient { /// \brief Sets session options. /// /// \param[in] options RPC-layer hints for this call. - /// \param[in] session_options The session options to set. + /// \param[in] request The session options to set. ::arrow::Result SetSessionOptions( const FlightCallOptions& options, - const std::map& session_options) { - return impl_->SetSessionOptions(options, session_options); + const SetSessionOptionsRequest& request) { + return impl_->SetSessionOptions(options, request); } /// \brief Gets current session options. /// /// \param[in] options RPC-layer hints for this call. ::arrow::Result GetSessionOptions( - const FlightCallOptions& options) { - return impl_->GetSessionOptions(options); + const FlightCallOptions& options, + const GetSessionOptionsRequest& request) { + return impl_->GetSessionOptions(options, request); } /// \brief Explicitly closes the session if applicable. /// /// \param[in] options RPC-layer hints for this call. - ::arrow::Result CloseSession(const FlightCallOptions& options) { - return impl_->CloseSession(options); + ::arrow::Result CloseSession(const FlightCallOptions& options, + const CloseSessionRequest& request) { + return impl_->CloseSession(options, request); } /// \brief Extends the expiration of a FlightEndpoint. diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index 31cebd9efd474..6a04f18d7322c 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -270,17 +270,6 @@ arrow::Result ParseActionCancelQueryRequest( return result; } -arrow::Result ParseActionCloseSessionRequest( - const google::protobuf::Any& any) { - pb::CloseSessionRequest command; - if (!any.UnpackTo(&command)) { - return Status::Invalid("Unable to unpack CloseSessionRequest"); - } - - CloseSessionRequest result; - return result; -} - arrow::Result ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) { pb::sql::ActionCreatePreparedStatementRequest command; @@ -371,64 +360,6 @@ arrow::Result ParseActionEndTransactionRequest( return result; } -arrow::Result ParseActionSetSessionOptionsRequest( - const google::protobuf::Any& any) { - pb::SetSessionOptionsRequest command; - if (!any.UnpackTo(&command)) { - return Status::Invalid("Unable to unpack SetSessionOptionsRequest"); - } - - SetSessionOptionsRequest result; - if (command.session_options_size() > 0) { - for (const auto & [name, pb_val] : command.session_options()) { - SessionOptionValue val; - switch (pb_val.option_value_case()) { - case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: - return Status::Invalid("Unset SessionOptionValue for name '" + name + "'"); - case pb::SessionOptionValue::kStringValue: - val = pb_val.string_value(); - break; - case pb::SessionOptionValue::kBoolValue: - val = pb_val.bool_value(); - break; - case pb::SessionOptionValue::kInt32Value: - val = pb_val.int32_value(); - break; - case pb::SessionOptionValue::kInt64Value: - val = pb_val.int64_value(); - break; - case pb::SessionOptionValue::kFloatValue: - val = pb_val.float_value(); - break; - case pb::SessionOptionValue::kDoubleValue: - val = pb_val.double_value(); - break; - case pb::SessionOptionValue::kStringListValue: - val.emplace>(); - std::get>(val) - .reserve(pb_val.string_list_value().values_size()); - for (const std::string& s : pb_val.string_list_value().values()) - std::get>(val).push_back(s); - break; - } - result.session_options[name] = std::move(val); - } - } - - return result; -} - -arrow::Result ParseActionGetSessionOptionsRequest( - const google::protobuf::Any& any) { - pb::GetSessionOptionsRequest command; - if (!any.UnpackTo(&command)) { - return Status::Invalid("Unable to unpack GetSessionOptionsRequest"); - } - - GetSessionOptionsRequest result; - return result; -} - arrow::Result PackActionResult(const google::protobuf::Message& message) { google::protobuf::Any any; #if PROTOBUF_VERSION >= 3015000 @@ -511,94 +442,21 @@ arrow::Result PackActionResult(ActionCreatePreparedStatementResult resul return PackActionResult(pb_result); } - -// PHOXME remove code from 3 impls after serde stuff is written and/or *moved* arrow::Result PackActionResult(SetSessionOptionsResult result) { ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString()); - return Result(Buffer::FromString(std::move(serialized)); - - - /* pb::SetSessionOptionsResult pb_result; - auto* pb_results_map = pb_result.mutable_results(); - for (const auto& [opt_name, res] : result.results) { - pb::ActionSetSessionOptionsResult_SetSessionOptionResult val; - switch (res) { - case SetSessionOptionResult::kUnspecified: - val = pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_UNSPECIFIED; - break; - case SetSessionOptionResult::kOk: - val = pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_OK; - break; - case SetSessionOptionResult::kInvalidResult: - val = pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_INVALID_VALUE; - break; - case SetSessionOptionResult::kError: - val = pb::SetSessionOptionsResult::SET_SESSION_OPTION_RESULT_ERROR; - break; - } - (*pb_results_map)[opt_name] = val; - } - return PackActionResult(pb_result); */ + return Result{Buffer::FromString(std::move(serialized))}; } arrow::Result PackActionResult(GetSessionOptionsResult result) { ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString()); - return Result(Buffer::FromString(std::move(serialized)); - - - /* pb::GetSessionOptionsResult pb_result; - auto* pb_results = pb_result.mutable_session_options(); - for (const auto& [name, opt_value] : result.session_options) { - pb::SessionOptionValue pb_opt_value; - - if (opt_value.index() == std::variant_npos) - return Status::Invalid("Undefined SessionOptionValue type"); - - std::visit(overloaded{ - // TODO move this somewhere common that can have Proto-involved code - [&](std::string v) { pb_opt_value.set_string_value(v); }, - [&](bool v) { pb_opt_value.set_bool_value(v); }, - [&](int32_t v) { pb_opt_value.set_int32_value(v); }, - [&](int64_t v) { pb_opt_value.set_int64_value(v); }, - [&](float v) { pb_opt_value.set_float_value(v); }, - [&](double v) { pb_opt_value.set_double_value(v); }, - [&](std::vector v) { - auto* string_list_value = pb_opt_value.mutable_string_list_value(); - for (const std::string& s : v) - string_list_value->add_values(s); - } - }, opt_value); - (*pb_results)[name] = std::move(pb_opt_value); - } - - return PackActionResult(pb_result); */ + return Result{Buffer::FromString(std::move(serialized))}; } arrow::Result PackActionResult(CloseSessionResult result) { ARROW_ASSIGN_OR_RAISE(auto serialized, result.SerializeToString()); - return Result(Buffer::FromString(std::move(serialized)); - - - /* pb::ActionCloseSessionResult pb_result; - switch (result) { - case CloseSessionResult::kUnspecified: - pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_UNSPECIFIED); - break; - case CloseSessionResult::kClosed: - pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSED); - break; - case CloseSessionResult::kClosing: - pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_CLOSING); - break; - case CloseSessionResult::kNotClosable: - pb_result.set_result(pb::ActionCloseSessionResult::CLOSE_RESULT_NOT_CLOSEABLE); - break; - } - return PackActionResult(pb_result);*/ + return Result{Buffer::FromString(std::move(serialized))}; } -// /PHOXME - } // namespace arrow::Result StatementQueryTicket::Deserialize( @@ -961,7 +819,7 @@ Status FlightSqlServerBase::DoAction(const ServerCallContext& context, results.push_back(std::move(packed_result)); } else if (action.type == ActionType::kGetSessionOptions.type) { std::string_view body(*action.body); - ARROW_ASSIGN_OR_RAISE(auto request, GetSessionOptionsRequest::Deserialize(body));) + ARROW_ASSIGN_OR_RAISE(auto request, GetSessionOptionsRequest::Deserialize(body)); ARROW_ASSIGN_OR_RAISE(auto result, GetSessionOptions(context, request)); ARROW_ASSIGN_OR_RAISE(auto packed_result, PackActionResult(std::move(result))); diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 74c47704d7722..d1f59be1976d8 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -161,15 +161,15 @@ std::shared_ptr MakeServerSessionMiddlewareFactory() { new ServerSessionMiddlewareFactory()); } -SessionOptionValue FlightSqlSession::GetSessionOption(const std::string_view k) { +SessionOptionValue FlightSqlSession::GetSessionOption(const std::string& k) { const std::shared_lock l(map_lock_); return map_.at(k); } -void FlightSqlSession::SetSessionOption(const std::string_view, const SessionOptionValue& v) { +void FlightSqlSession::SetSessionOption(const std::string& k, const SessionOptionValue& v) { const std::unique_lock l(map_lock_); map_[k] = v; } -void FlightSqlSession::EraseSessionOption(const std::string_view) { +void FlightSqlSession::EraseSessionOption(const std::string& k) { const std::unique_lock l(map_lock_); map_.erase(k); } diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 41f8736d4fc78..119135e9ef258 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -40,11 +40,11 @@ class FlightSqlSession { std::shared_mutex map_lock_; public: /// \brief Get session option by key - SessionOptionValue GetSessionOption(const std::string_view); + SessionOptionValue GetSessionOption(const std::string&); /// \brief Set session option by key to given value - void SetSessionOption(const std::string_view, const SessionOptionValue&); + void SetSessionOption(const std::string&, const SessionOptionValue&); /// \brief Idempotently remove key from this call's Session, if Session & key exist - void EraseSessionOption(const std::string_view); + void EraseSessionOption(const std::string&); }; /// \brief A middleware to handle Session option persistence and related *Cookie headers. diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index b0521e4ca36e1..5423ef590a1f4 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -473,36 +473,49 @@ arrow::Result CancelFlightInfoRequest::Deserialize( return out; } -// Helper for stringifying maps containing various types -template -ostream& operator<<(std::map) { - std::stringstream ss; +// Helpers for stringifying maps containing various types +std::ostream& operator<<(std::ostream& os, std::vector v) { + os << '['; + std::string sep = ""; + for (const auto& x : v) { + os << sep << '"' << x << '"'; + sep = ", "; + } + os << ']'; - ss << '{'; + return os; +} +template +std::ostream& operator<<(std::ostream& os, std::map m) { + os << '{'; std::string sep = ""; - for (const auto& [k, v] : session_options) { - std::cout << sep << '[' << k << "]: '" << v << "', "; + for (const auto& [k, v] : m) { + os << sep << '[' << k << "]: '" << v; sep = ", "; } - ss << '}'; + os << '}'; - return ss.str(); + return os; } static bool CompareSessionOptionMaps( const std::map& a, const std::map& b) { - if (a.session_options.size() != b.session_options.size()) { + if (a.size() != b.size()) { return false; } - for (const auto & [k, v] : a.session_options) { - if (!b.session_options.contains(k)) { + for (const auto & [k, v] : a) { + if (!b.count(k)) { return false; } - const auto& b_v = b.session_options[k]; - if (v.index() != b_v.index()) { - return false; - } - if (v != b_v) { + try { + const auto& b_v = b.at(k); + if (v.index() != b_v.index()) { + return false; + } + if (v != b_v) { + return false; + } + } catch ( const std::out_of_range& e ) { return false; } } @@ -514,8 +527,7 @@ static bool CompareSessionOptionMaps( std::string SetSessionOptionsRequest::ToString() const { std::stringstream ss; - ss << " session_options; std::string ToString() const; @@ -837,7 +842,7 @@ struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsRequest { return left.Equals(right); } friend bool operator!=(const SetSessionOptionsRequest& left, - const SetSessionOptionsRequest& right)){ + const SetSessionOptionsRequest& right) { return !(left == right); } @@ -850,7 +855,7 @@ struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsRequest { }; /// \brief The result(s) of setting session option(s). -struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsResult { +struct ARROW_FLIGHT_EXPORT SetSessionOptionsResult { std::map statuses; std::string ToString() const; @@ -861,7 +866,7 @@ struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsResult { return left.Equals(right); } friend bool operator!=(const SetSessionOptionsResult& left, - const SetSessionOptionsResult& right)){ + const SetSessionOptionsResult& right) { return !(left == right); } @@ -874,7 +879,7 @@ struct ARROW_FLIGHT_SQL_EXPORT SetSessionOptionsResult { }; /// \brief A request to get current session options. -struct ARROW_FLIGHT_SQL_EXPORT GetSessionOptionsRequest { +struct ARROW_FLIGHT_EXPORT GetSessionOptionsRequest { std::string ToString() const; bool Equals(const GetSessionOptionsRequest& other) const; @@ -883,7 +888,7 @@ struct ARROW_FLIGHT_SQL_EXPORT GetSessionOptionsRequest { return left.Equals(right); } friend bool operator!=(const GetSessionOptionsRequest& left, - const GetSessionOptionsRequest& right)){ + const GetSessionOptionsRequest& right) { return !(left == right); } @@ -896,7 +901,7 @@ struct ARROW_FLIGHT_SQL_EXPORT GetSessionOptionsRequest { }; /// \brief The current session options. -struct ARROW_FLIGHT_SQL_EXPORT GetSessionOptionsResult { +struct ARROW_FLIGHT_EXPORT GetSessionOptionsResult { std::map session_options; std::string ToString() const; @@ -907,7 +912,7 @@ struct ARROW_FLIGHT_SQL_EXPORT GetSessionOptionsResult { return left.Equals(right); } friend bool operator!=(const GetSessionOptionsResult& left, - const GetSessionOptionsResult& right)){ + const GetSessionOptionsResult& right) { return !(left == right); } @@ -920,7 +925,7 @@ struct ARROW_FLIGHT_SQL_EXPORT GetSessionOptionsResult { }; /// \brief A request to close the open client session. -struct ARROW_FLIGHT_SQL_EXPORT CloseSessionRequest { std::string ToString() const; +struct ARROW_FLIGHT_EXPORT CloseSessionRequest { std::string ToString() const; bool Equals(const CloseSessionRequest& other) const; friend bool operator==(const CloseSessionRequest& left, @@ -928,7 +933,7 @@ struct ARROW_FLIGHT_SQL_EXPORT CloseSessionRequest { std::string ToString() con return left.Equals(right); } friend bool operator!=(const CloseSessionRequest& left, - const CloseSessionRequest& right)){ + const CloseSessionRequest& right) { return !(left == right); } @@ -941,7 +946,7 @@ struct ARROW_FLIGHT_SQL_EXPORT CloseSessionRequest { std::string ToString() con }; /// \brief The result of attempting to close the client session. -struct ARROW_FLIGHT_SQL_EXPORT CloseSessionResult { +struct ARROW_FLIGHT_EXPORT CloseSessionResult { CloseSessionStatus status; std::string ToString() const; @@ -952,7 +957,7 @@ struct ARROW_FLIGHT_SQL_EXPORT CloseSessionResult { return left.Equals(right); } friend bool operator!=(const CloseSessionResult& left, - const CloseSessionResult& right)){ + const CloseSessionResult& right) { return !(left == right); } @@ -962,7 +967,7 @@ struct ARROW_FLIGHT_SQL_EXPORT CloseSessionResult { /// \brief Deserialize this message from its wire-format representation. static arrow::Result Deserialize(std::string_view serialized); -} +}; /// \brief An iterator to FlightInfo instances returned by ListFlights. class ARROW_FLIGHT_EXPORT FlightListing { diff --git a/format/Flight.proto b/format/Flight.proto index 99e1a1671259c..614129de12a5a 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -18,6 +18,7 @@ syntax = "proto3"; import "google/protobuf/timestamp.proto"; +import "google/protobuf/descriptor.proto"; option java_package = "org.apache.arrow.flight.impl"; option go_package = "github.com/apache/arrow/go/arrow/flight/gen/flight"; From c234edde4e71aa0e09d90510e8d7512573b94a23 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 1 Nov 2023 19:42:20 -0700 Subject: [PATCH 040/195] Fix last build issue --- cpp/src/arrow/flight/types.cc | 17 ++++++++++ cpp/src/arrow/flight/types.h | 60 ++++++++++------------------------- 2 files changed, 33 insertions(+), 44 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 5423ef590a1f4..41b4603a6363b 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -473,6 +473,16 @@ arrow::Result CancelFlightInfoRequest::Deserialize( return out; } +std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& r) { + os << SetSessionOptionStatusNames[static_cast(r)]; + return os; +} + +std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& r) { + os << CloseSessionStatusNames[static_cast(r)]; + return os; +} + // Helpers for stringifying maps containing various types std::ostream& operator<<(std::ostream& os, std::vector v) { os << '['; @@ -483,8 +493,14 @@ std::ostream& operator<<(std::ostream& os, std::vector v) { } os << ']'; + return os; +} + +std::ostream& operator<<(std::ostream& os, const SessionOptionValue& v) { + std::visit([&](const auto& x) { os << x; }, v); return os; } + template std::ostream& operator<<(std::ostream& os, std::map m) { os << '{'; @@ -497,6 +513,7 @@ std::ostream& operator<<(std::ostream& os, std::map m) { return os; } + static bool CompareSessionOptionMaps( const std::map& a, const std::map& b) { diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 900085ca7aa65..8604a58c0f15c 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -767,10 +767,6 @@ struct ARROW_FLIGHT_EXPORT CancelFlightInfoRequest { /// \brief Variant supporting all possible value types for {Set,Get}SessionOptions using SessionOptionValue = std::variant>; -std::ostream& operator<<(std::ostream& os, const SessionOptionValue& v) { - std::visit([&](const auto& x) { os << x; }, v); - return os; -} /// \brief The result of setting a session option. enum class SetSessionOptionStatus : int8_t { @@ -781,29 +777,15 @@ enum class SetSessionOptionStatus : int8_t { kInvalidValue, kError }; -std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& r) { - switch (r) { - case SetSessionOptionStatus::kUnspecified: - os << "Unspecified"; - break; - case SetSessionOptionStatus::kOk: - os << "Ok"; - break; - case SetSessionOptionStatus::kOkMapped: - os << "OkMapped"; - break; - case SetSessionOptionStatus::kInvalidKey: - os << "InvalidName"; - break; - case SetSessionOptionStatus::kInvalidValue: - os << "InvalidValue"; - break; - case SetSessionOptionStatus::kError: - os << "Error"; - break; - } - return os; -} +static std::string SetSessionOptionStatusNames[] = { + "Unspecified", + "Ok", + "OkMapped", + "InvalidKey", + "InvalidValue", + "Error" +}; +std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& r); /// \brief The result of closing a session. enum class CloseSessionStatus : int8_t { @@ -812,23 +794,13 @@ enum class CloseSessionStatus : int8_t { kClosing, kNotClosable }; -std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& r) { - switch (r) { - case CloseSessionStatus::kUnspecified: - os << "Unspecified"; - break; - case CloseSessionStatus::kClosed: - os << "Closed"; - break; - case CloseSessionStatus::kClosing: - os << "Closing"; - break; - case CloseSessionStatus::kNotClosable: - os << "NotClosable"; - break; - } - return os; -} +static std::string CloseSessionStatusNames[] = { + "Unspecified", + "Closed", + "Closing", + "NotClosable" +}; +std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& r); /// \brief A request to set a set of session options by key/value. struct ARROW_FLIGHT_EXPORT SetSessionOptionsRequest { From 01fdb1839a7c3c1d6b0a8d7d41354905aa97fcee Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 2 Nov 2023 11:22:28 -0700 Subject: [PATCH 041/195] [builds] Remote extraneous comments --- cpp/src/arrow/flight/serialization_internal.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 625d0c0a85a58..31c62704e3f76 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -442,8 +442,8 @@ Status ToProto(const SessionOptionValue& val, // map -Status FromProto(const google::protobuf::Map& pb_map, //PHOXME maybe need to include google/protobuf/map.h ? shouldn't this be brought in by other headers? +Status FromProto(const google::protobuf::Map& pb_map, std::map* map) { if (pb_map.size() == 0) { return Status::OK(); From 1f2262c6e250ea83d5c2bbd8e97f28d56b6517e4 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 2 Nov 2023 12:01:48 -0700 Subject: [PATCH 042/195] [builds] Some PR fixups --- cpp/src/arrow/flight/client.h | 4 ++-- cpp/src/arrow/flight/serialization_internal.cc | 2 +- cpp/src/arrow/flight/sql/client.cc | 1 - .../arrow/flight/sql/server_session_middleware.cc | 15 +++++++++------ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/cpp/src/arrow/flight/client.h b/cpp/src/arrow/flight/client.h index 68c9140d9a51c..0a81eea92e845 100644 --- a/cpp/src/arrow/flight/client.h +++ b/cpp/src/arrow/flight/client.h @@ -386,10 +386,10 @@ class ARROW_FLIGHT_EXPORT FlightClient { /// \\brief Set server session option(s) by key/value. Sessions are generally /// persisted via HTTP cookies. /// \param[in] options Per-RPC options -/// \param[in] session_options The server session options to set +/// \param[in] request The server session options to set ::arrow::Result SetSessionOptions( const FlightCallOptions& options, - const SetSessionOptionsRequest& session_options); + const SetSessionOptionsRequest& request); /// \\brief Get the current server session options. The session is generally /// accessed via an HTTP cookie. diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 31c62704e3f76..6d32c5b201ae6 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -445,7 +445,7 @@ Status ToProto(const SessionOptionValue& val, Status FromProto(const google::protobuf::Map& pb_map, std::map* map) { - if (pb_map.size() == 0) { + if (pb_map.empty()) { return Status::OK(); } for (auto& [key, pb_val] : pb_map) { diff --git a/cpp/src/arrow/flight/sql/client.cc b/cpp/src/arrow/flight/sql/client.cc index 9885ddc939996..d0552e33df5c2 100644 --- a/cpp/src/arrow/flight/sql/client.cc +++ b/cpp/src/arrow/flight/sql/client.cc @@ -797,7 +797,6 @@ ::arrow::Result FlightSqlClient::CancelQuery( return Status::IOError("Server returned unknown result ", result.result()); } - Status FlightSqlClient::Close() { return impl_->Close(); } std::ostream& operator<<(std::ostream& os, CancelResult result) { diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index d1f59be1976d8..12a354f542e39 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -79,16 +79,16 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { for (const std::pair& cookie : cookies) { if (cookie.first == kSessionCookieName) { session_id = cookie.second; - if (!session_id.length()) + if (session_id.empty()) return Status::Invalid( "Empty " + static_cast(kSessionCookieName) + " cookie value."); } } - if (session_id.length()) break; + if (!session_id.empty()) break; } - if (!session_id.length()) { + if (session_id.empty()) { // No cookie was found *middleware = std::shared_ptr( new ServerSessionMiddleware(this, incoming_headers)); @@ -130,7 +130,8 @@ ServerSessionMiddleware::ServerSessionMiddleware( ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, std::shared_ptr session, std::string session_id) - : factory_(factory), headers_(headers), session_(session), existing_session(true) {} + : factory_(factory), headers_(headers), session_(std::move(session)), + session_id_(std::move(session_id)), existing_session(true) {} void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { if (!existing_session && session_) { @@ -145,17 +146,17 @@ void ServerSessionMiddleware::CallCompleted(const Status&) {} bool ServerSessionMiddleware::HasSession() const { return static_cast(session_); } + std::shared_ptr ServerSessionMiddleware::GetSession() { if (!session_) session_ = factory_->GetNewSession(&session_id_); return session_; } + const CallHeaders& ServerSessionMiddleware::GetCallHeaders() const { return headers_; } - - std::shared_ptr MakeServerSessionMiddlewareFactory() { return std::shared_ptr( new ServerSessionMiddlewareFactory()); @@ -165,10 +166,12 @@ SessionOptionValue FlightSqlSession::GetSessionOption(const std::string& k) { const std::shared_lock l(map_lock_); return map_.at(k); } + void FlightSqlSession::SetSessionOption(const std::string& k, const SessionOptionValue& v) { const std::unique_lock l(map_lock_); map_[k] = v; } + void FlightSqlSession::EraseSessionOption(const std::string& k) { const std::unique_lock l(map_lock_); map_.erase(k); From 69f35ec2eeec684b6d78cfd37e78d26c80514c98 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 2 Nov 2023 13:27:50 -0700 Subject: [PATCH 043/195] [builds] More PR feedback --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 8 ++++++-- cpp/src/arrow/flight/sql/server_session_middleware.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 12a354f542e39..557b3d6402d58 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -162,9 +162,13 @@ std::shared_ptr MakeServerSessionMiddlewareFactory() { new ServerSessionMiddlewareFactory()); } -SessionOptionValue FlightSqlSession::GetSessionOption(const std::string& k) { +::arrow::Result FlightSqlSession::GetSessionOption(const std::string& k) { const std::shared_lock l(map_lock_); - return map_.at(k); + try { + return map_.at(k); + } catch (const std::out_of_range& e) { + return ::arrow::Status::KeyError("Session option key '" + k + "' not found."); + } } void FlightSqlSession::SetSessionOption(const std::string& k, const SessionOptionValue& v) { diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 119135e9ef258..84c7b3bb9bb78 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -40,7 +40,7 @@ class FlightSqlSession { std::shared_mutex map_lock_; public: /// \brief Get session option by key - SessionOptionValue GetSessionOption(const std::string&); + ::arrow::Result GetSessionOption(const std::string&); /// \brief Set session option by key to given value void SetSessionOption(const std::string&, const SessionOptionValue&); /// \brief Idempotently remove key from this call's Session, if Session & key exist From 5b2cee7c443a974009e26e009a08b16feb3850d8 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 2 Nov 2023 13:33:17 -0700 Subject: [PATCH 044/195] [builds] More PR feedback --- cpp/src/arrow/flight/types.cc | 50 ++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 41b4603a6363b..021737b3402a0 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -514,30 +514,32 @@ std::ostream& operator<<(std::ostream& os, std::map m) { return os; } -static bool CompareSessionOptionMaps( - const std::map& a, - const std::map& b) { - if (a.size() != b.size()) { - return false; - } - for (const auto & [k, v] : a) { - if (!b.count(k)) { - return false; - } - try { - const auto& b_v = b.at(k); - if (v.index() != b_v.index()) { - return false; - } - if (v != b_v) { - return false; - } - } catch ( const std::out_of_range& e ) { - return false; - } - } - return true; -} +namespace { + static bool CompareSessionOptionMaps( + const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto & [k, v] : a) { + if (!b.count(k)) { + return false; + } + try { + const auto& b_v = b.at(k); + if (v.index() != b_v.index()) { + return false; + } + if (v != b_v) { + return false; + } + } catch ( const std::out_of_range& e ) { + return false; + } + } + return true; + } +} // SetSessionOptionsRequest From 2affc0be4381a4add571a584d7930ca295615b52 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 2 Nov 2023 15:36:43 -0700 Subject: [PATCH 045/195] [builds] Fix linter errors --- cpp/src/arrow/flight/client.cc | 2 +- cpp/src/arrow/flight/client.h | 2 +- cpp/src/arrow/flight/sql/server.cc | 4 +- .../flight/sql/server_session_middleware.cc | 9 ++-- cpp/src/arrow/flight/types.cc | 52 +++++++++---------- cpp/src/arrow/flight/types.h | 26 +++++----- 6 files changed, 49 insertions(+), 46 deletions(-) diff --git a/cpp/src/arrow/flight/client.cc b/cpp/src/arrow/flight/client.cc index 1e5a843d19d66..fe2410e57fb9c 100644 --- a/cpp/src/arrow/flight/client.cc +++ b/cpp/src/arrow/flight/client.cc @@ -731,7 +731,7 @@ FlightClient::SetSessionOptions( } ::arrow::Result -FlightClient::GetSessionOptions ( +FlightClient::GetSessionOptions( const FlightCallOptions& options, const GetSessionOptionsRequest& request) { RETURN_NOT_OK(CheckOpen()); diff --git a/cpp/src/arrow/flight/client.h b/cpp/src/arrow/flight/client.h index 0a81eea92e845..573621c76edc0 100644 --- a/cpp/src/arrow/flight/client.h +++ b/cpp/src/arrow/flight/client.h @@ -394,7 +394,7 @@ ::arrow::Result SetSessionOptions( /// \\brief Get the current server session options. The session is generally /// accessed via an HTTP cookie. /// \param[in] options Per-RPC options -::arrow::Result GetSessionOptions ( +::arrow::Result GetSessionOptions( const FlightCallOptions& options, const GetSessionOptionsRequest& request); diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index 6a04f18d7322c..5d90f63e36043 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -1173,13 +1173,13 @@ Status FlightSqlServerBase::EndTransaction(const ServerCallContext& context, return Status::NotImplemented("EndTransaction not implemented"); } -arrow::Result FlightSqlServerBase::SetSessionOptions ( +arrow::Result FlightSqlServerBase::SetSessionOptions( const ServerCallContext& context, const SetSessionOptionsRequest& request) { return Status::NotImplemented("SetSessionOptions not implemented"); } -arrow::Result FlightSqlServerBase::GetSessionOptions ( +arrow::Result FlightSqlServerBase::GetSessionOptions( const ServerCallContext& context, const GetSessionOptionsRequest& request) { return Status::NotImplemented("GetSessionOptions not implemented"); diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 557b3d6402d58..8ce00f58a6fd9 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -58,8 +58,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { const size_t val_pos = tok.find(pair_sep); result.emplace_back( tok.substr(0, val_pos), - tok.substr(val_pos + pair_sep_len, std::string::npos) - ); + tok.substr(val_pos + pair_sep_len, std::string::npos)); } return result; @@ -162,7 +161,8 @@ std::shared_ptr MakeServerSessionMiddlewareFactory() { new ServerSessionMiddlewareFactory()); } -::arrow::Result FlightSqlSession::GetSessionOption(const std::string& k) { +::arrow::Result +FlightSqlSession::GetSessionOption(const std::string& k) { const std::shared_lock l(map_lock_); try { return map_.at(k); @@ -171,7 +171,8 @@ ::arrow::Result FlightSqlSession::GetSessionOption(const std } } -void FlightSqlSession::SetSessionOption(const std::string& k, const SessionOptionValue& v) { +void FlightSqlSession::SetSessionOption( + const std::string& k, const SessionOptionValue& v) { const std::unique_lock l(map_lock_); map_[k] = v; } diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 021737b3402a0..c49f52d42794a 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -494,7 +494,7 @@ std::ostream& operator<<(std::ostream& os, std::vector v) { os << ']'; return os; -} +} std::ostream& operator<<(std::ostream& os, const SessionOptionValue& v) { std::visit([&](const auto& x) { os << x; }, v); @@ -516,30 +516,30 @@ std::ostream& operator<<(std::ostream& os, std::map m) { namespace { static bool CompareSessionOptionMaps( - const std::map& a, - const std::map& b) { - if (a.size() != b.size()) { - return false; - } - for (const auto & [k, v] : a) { - if (!b.count(k)) { - return false; - } - try { - const auto& b_v = b.at(k); - if (v.index() != b_v.index()) { - return false; - } - if (v != b_v) { - return false; - } - } catch ( const std::out_of_range& e ) { - return false; - } - } - return true; - } -} + const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto & [k, v] : a) { + if (!b.count(k)) { + return false; + } + try { + const auto& b_v = b.at(k); + if (v.index() != b_v.index()) { + return false; + } + if (v != b_v) { + return false; + } + } catch ( const std::out_of_range& e ) { + return false; + } + } + return true; + } +} // namespace // SetSessionOptionsRequest @@ -674,7 +674,7 @@ GetSessionOptionsRequest::Deserialize(std::string_view serialized) { std::string GetSessionOptionsResult::ToString() const { std::stringstream ss; - + ss << " Date: Thu, 2 Nov 2023 16:28:58 -0700 Subject: [PATCH 046/195] [builds] clang-format --- cpp/src/arrow/flight/client.cc | 32 ++--- cpp/src/arrow/flight/client.h | 39 +++--- .../arrow/flight/serialization_internal.cc | 74 +++++------ cpp/src/arrow/flight/serialization_internal.h | 12 +- cpp/src/arrow/flight/sql/client.h | 8 +- cpp/src/arrow/flight/sql/protocol_internal.h | 2 +- cpp/src/arrow/flight/sql/server.cc | 37 +++--- cpp/src/arrow/flight/sql/server.h | 11 +- .../flight/sql/server_session_middleware.cc | 62 ++++----- .../flight/sql/server_session_middleware.h | 25 ++-- cpp/src/arrow/flight/types.cc | 121 ++++++++---------- cpp/src/arrow/flight/types.h | 49 ++----- cpp/src/arrow/json/test_common.h | 2 +- cpp/src/arrow/util/tracing_internal.h | 11 +- cpp/src/gandiva/gdv_hash_function_stubs.cc | 2 +- .../gandiva/precompiled/string_ops_test.cc | 6 +- 16 files changed, 203 insertions(+), 290 deletions(-) diff --git a/cpp/src/arrow/flight/client.cc b/cpp/src/arrow/flight/client.cc index fe2410e57fb9c..b096ec470763b 100644 --- a/cpp/src/arrow/flight/client.cc +++ b/cpp/src/arrow/flight/client.cc @@ -713,51 +713,45 @@ arrow::Result FlightClient::DoExchange( return result; } -::arrow::Result -FlightClient::SetSessionOptions( - const FlightCallOptions& options, - const SetSessionOptionsRequest& request) { +::arrow::Result FlightClient::SetSessionOptions( + const FlightCallOptions& options, const SetSessionOptionsRequest& request) { RETURN_NOT_OK(CheckOpen()); RETURN_NOT_OK(CheckOpen()); ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); Action action{ActionType::kSetSessionOptions.type, Buffer::FromString(body)}; ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); ARROW_ASSIGN_OR_RAISE(auto result, stream->Next()); - ARROW_ASSIGN_OR_RAISE(auto set_session_options_result, - SetSessionOptionsResult::Deserialize( - std::string_view(*result->body))); + ARROW_ASSIGN_OR_RAISE( + auto set_session_options_result, + SetSessionOptionsResult::Deserialize(std::string_view(*result->body))); ARROW_RETURN_NOT_OK(stream->Drain()); return set_session_options_result; } -::arrow::Result -FlightClient::GetSessionOptions( - const FlightCallOptions& options, - const GetSessionOptionsRequest& request) { +::arrow::Result FlightClient::GetSessionOptions( + const FlightCallOptions& options, const GetSessionOptionsRequest& request) { + RETURN_NOT_OK(CheckOpen()); RETURN_NOT_OK(CheckOpen()); - RETURN_NOT_OK(CheckOpen()); ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); Action action{ActionType::kGetSessionOptions.type, Buffer::FromString(body)}; ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); ARROW_ASSIGN_OR_RAISE(auto result, stream->Next()); - ARROW_ASSIGN_OR_RAISE(auto get_session_options_result, - GetSessionOptionsResult::Deserialize( - std::string_view(*result->body))); + ARROW_ASSIGN_OR_RAISE( + auto get_session_options_result, + GetSessionOptionsResult::Deserialize(std::string_view(*result->body))); ARROW_RETURN_NOT_OK(stream->Drain()); return get_session_options_result; } ::arrow::Result FlightClient::CloseSession( - const FlightCallOptions& options, - const CloseSessionRequest& request) { + const FlightCallOptions& options, const CloseSessionRequest& request) { RETURN_NOT_OK(CheckOpen()); ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); Action action{ActionType::kCloseSession.type, Buffer::FromString(body)}; ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); ARROW_ASSIGN_OR_RAISE(auto result, stream->Next()); ARROW_ASSIGN_OR_RAISE(auto close_session_result, - CloseSessionResult::Deserialize( - std::string_view(*result->body))); + CloseSessionResult::Deserialize(std::string_view(*result->body))); ARROW_RETURN_NOT_OK(stream->Drain()); return close_session_result; } diff --git a/cpp/src/arrow/flight/client.h b/cpp/src/arrow/flight/client.h index 573621c76edc0..68ba73a8cea9d 100644 --- a/cpp/src/arrow/flight/client.h +++ b/cpp/src/arrow/flight/client.h @@ -383,27 +383,24 @@ class ARROW_FLIGHT_EXPORT FlightClient { return DoExchange({}, descriptor); } -/// \\brief Set server session option(s) by key/value. Sessions are generally -/// persisted via HTTP cookies. -/// \param[in] options Per-RPC options -/// \param[in] request The server session options to set -::arrow::Result SetSessionOptions( - const FlightCallOptions& options, - const SetSessionOptionsRequest& request); - -/// \\brief Get the current server session options. The session is generally -/// accessed via an HTTP cookie. -/// \param[in] options Per-RPC options -::arrow::Result GetSessionOptions( - const FlightCallOptions& options, - const GetSessionOptionsRequest& request); - -/// \\brief Close/invalidate the current server session. The session is generally -/// accessed via an HTTP cookie. -/// \param[in] options Per-RPC options -::arrow::Result CloseSession( - const FlightCallOptions& options, - const CloseSessionRequest& request); + /// \\brief Set server session option(s) by key/value. Sessions are generally + /// persisted via HTTP cookies. + /// \param[in] options Per-RPC options + /// \param[in] request The server session options to set + ::arrow::Result SetSessionOptions( + const FlightCallOptions& options, const SetSessionOptionsRequest& request); + + /// \\brief Get the current server session options. The session is generally + /// accessed via an HTTP cookie. + /// \param[in] options Per-RPC options + ::arrow::Result GetSessionOptions( + const FlightCallOptions& options, const GetSessionOptionsRequest& request); + + /// \\brief Close/invalidate the current server session. The session is generally + /// accessed via an HTTP cookie. + /// \param[in] options Per-RPC options + ::arrow::Result CloseSession(const FlightCallOptions& options, + const CloseSessionRequest& request); /// \brief Explicitly shut down and clean up the client. /// diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 6d32c5b201ae6..0fd14c5037620 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -28,9 +28,11 @@ #include "arrow/status.h" // Lambda helper & CTAD -template -struct overloaded : Ts... { using Ts::operator()...; }; -template // CTAD will not be needed for >=C++20 +template +struct overloaded : Ts... { + using Ts::operator()...; +}; +template // CTAD will not be needed for >=C++20 overloaded(Ts...) -> overloaded; namespace arrow { @@ -388,8 +390,7 @@ Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out) { // SessionOptionValue -Status FromProto(const pb::SessionOptionValue& pb_val, - SessionOptionValue* val) { +Status FromProto(const pb::SessionOptionValue& pb_val, SessionOptionValue* val) { switch (pb_val.option_value_case()) { case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: return Status::Invalid("Unset SessionOptionValue found"); @@ -413,8 +414,8 @@ Status FromProto(const pb::SessionOptionValue& pb_val, break; case pb::SessionOptionValue::kStringListValue: (*val).emplace>(); - std::get>(*val) - .reserve(pb_val.string_list_value().values_size()); + std::get>(*val).reserve( + pb_val.string_list_value().values_size()); for (const std::string& s : pb_val.string_list_value().values()) std::get>(*val).push_back(s); break; @@ -422,28 +423,24 @@ Status FromProto(const pb::SessionOptionValue& pb_val, return Status::OK(); } -Status ToProto(const SessionOptionValue& val, - pb::SessionOptionValue* pb_val) { - std::visit(overloaded{ - [&](std::string v) { pb_val->set_string_value(v); }, - [&](bool v) { pb_val->set_bool_value(v); }, - [&](int32_t v) { pb_val->set_int32_value(v); }, - [&](int64_t v) { pb_val->set_int64_value(v); }, - [&](float v) { pb_val->set_float_value(v); }, - [&](double v) { pb_val->set_double_value(v); }, - [&](std::vector v) { - auto* string_list_value = pb_val->mutable_string_list_value(); - for (const std::string& s : v) - string_list_value->add_values(s); - } - }, val); +Status ToProto(const SessionOptionValue& val, pb::SessionOptionValue* pb_val) { + std::visit(overloaded{[&](std::string v) { pb_val->set_string_value(v); }, + [&](bool v) { pb_val->set_bool_value(v); }, + [&](int32_t v) { pb_val->set_int32_value(v); }, + [&](int64_t v) { pb_val->set_int64_value(v); }, + [&](float v) { pb_val->set_float_value(v); }, + [&](double v) { pb_val->set_double_value(v); }, + [&](std::vector v) { + auto* string_list_value = pb_val->mutable_string_list_value(); + for (const std::string& s : v) string_list_value->add_values(s); + }}, + val); return Status::OK(); } // map -Status FromProto(const google::protobuf::Map& pb_map, +Status FromProto(const google::protobuf::Map& pb_map, std::map* map) { if (pb_map.empty()) { return Status::OK(); @@ -456,7 +453,7 @@ Status FromProto(const google::protobuf::Map& map, google::protobuf::Map* pb_map) { - for (const auto & [key, val] : map) { + for (const auto& [key, val] : map) { RETURN_NOT_OK(ToProto(val, &(*pb_map)[key])); } return Status::OK(); @@ -466,15 +463,13 @@ Status ToProto(const std::map& map, Status FromProto(const pb::SetSessionOptionsRequest& pb_request, SetSessionOptionsRequest* request) { - RETURN_NOT_OK(FromProto(pb_request.session_options(), - &request->session_options)); + RETURN_NOT_OK(FromProto(pb_request.session_options(), &request->session_options)); return Status::OK(); } Status ToProto(const SetSessionOptionsRequest& request, pb::SetSessionOptionsRequest* pb_request) { - RETURN_NOT_OK(ToProto(request.session_options, - pb_request->mutable_session_options())); + RETURN_NOT_OK(ToProto(request.session_options, pb_request->mutable_session_options())); return Status::OK(); } @@ -513,15 +508,13 @@ Status ToProto(const GetSessionOptionsRequest& request, Status FromProto(const pb::GetSessionOptionsResult& pb_result, GetSessionOptionsResult* result) { - RETURN_NOT_OK(FromProto(pb_result.session_options(), - &result->session_options)); + RETURN_NOT_OK(FromProto(pb_result.session_options(), &result->session_options)); return Status::OK(); } Status ToProto(const GetSessionOptionsResult& result, - pb::GetSessionOptionsResult* pb_result) { - RETURN_NOT_OK(ToProto(result.session_options, - pb_result->mutable_session_options())); + pb::GetSessionOptionsResult* pb_result) { + RETURN_NOT_OK(ToProto(result.session_options, pb_result->mutable_session_options())); return Status::OK(); } @@ -532,24 +525,19 @@ Status FromProto(const pb::CloseSessionRequest& pb_request, return Status::OK(); } -Status ToProto(const CloseSessionRequest& request, - pb::CloseSessionRequest* pb_request) { +Status ToProto(const CloseSessionRequest& request, pb::CloseSessionRequest* pb_request) { return Status::OK(); } // CloseSessionResult -Status FromProto(const pb::CloseSessionResult& pb_result, - CloseSessionResult* result) { +Status FromProto(const pb::CloseSessionResult& pb_result, CloseSessionResult* result) { result->status = static_cast(pb_result.status()); return Status::OK(); } -Status ToProto(const CloseSessionResult& result, - pb::CloseSessionResult* pb_result) { - pb_result->set_status( - static_cast( - result.status)); +Status ToProto(const CloseSessionResult& result, pb::CloseSessionResult* pb_result) { + pb_result->set_status(static_cast(result.status)); return Status::OK(); } diff --git a/cpp/src/arrow/flight/serialization_internal.h b/cpp/src/arrow/flight/serialization_internal.h index 170715129525e..90dde87d3a5eb 100644 --- a/cpp/src/arrow/flight/serialization_internal.h +++ b/cpp/src/arrow/flight/serialization_internal.h @@ -74,10 +74,8 @@ Status FromProto(const pb::GetSessionOptionsRequest& pb_request, GetSessionOptionsRequest* request); Status FromProto(const pb::GetSessionOptionsResult& pb_result, GetSessionOptionsResult* result); -Status FromProto(const pb::CloseSessionRequest& pb_request, - CloseSessionRequest* request); -Status FromProto(const pb::CloseSessionResult& pb_result, - CloseSessionResult* result); +Status FromProto(const pb::CloseSessionRequest& pb_request, CloseSessionRequest* request); +Status FromProto(const pb::CloseSessionResult& pb_result, CloseSessionResult* result); Status ToProto(const Timestamp& timestamp, google::protobuf::Timestamp* pb_timestamp); Status ToProto(const FlightDescriptor& descr, pb::FlightDescriptor* pb_descr); @@ -105,10 +103,8 @@ Status ToProto(const GetSessionOptionsRequest& request, pb::GetSessionOptionsRequest* pb_request); Status ToProto(const GetSessionOptionsResult& result, pb::GetSessionOptionsResult* pb_result); -Status ToProto(const CloseSessionRequest& request, - pb::CloseSessionRequest* pb_request); -Status ToProto(const CloseSessionResult& result, - pb::CloseSessionResult* pb_result); +Status ToProto(const CloseSessionRequest& request, pb::CloseSessionRequest* pb_request); +Status ToProto(const CloseSessionResult& result, pb::CloseSessionResult* pb_result); Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out); diff --git a/cpp/src/arrow/flight/sql/client.h b/cpp/src/arrow/flight/sql/client.h index 5ad21a0162ee5..19cd2801bdd2e 100644 --- a/cpp/src/arrow/flight/sql/client.h +++ b/cpp/src/arrow/flight/sql/client.h @@ -18,8 +18,8 @@ #pragma once #include -#include #include +#include #include #include "arrow/flight/client.h" @@ -356,8 +356,7 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlClient { /// \param[in] options RPC-layer hints for this call. /// \param[in] request The session options to set. ::arrow::Result SetSessionOptions( - const FlightCallOptions& options, - const SetSessionOptionsRequest& request) { + const FlightCallOptions& options, const SetSessionOptionsRequest& request) { return impl_->SetSessionOptions(options, request); } @@ -365,8 +364,7 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlClient { /// /// \param[in] options RPC-layer hints for this call. ::arrow::Result GetSessionOptions( - const FlightCallOptions& options, - const GetSessionOptionsRequest& request) { + const FlightCallOptions& options, const GetSessionOptionsRequest& request) { return impl_->GetSessionOptions(options, request); } diff --git a/cpp/src/arrow/flight/sql/protocol_internal.h b/cpp/src/arrow/flight/sql/protocol_internal.h index 71e82eb83bb4f..dfe32abf0245d 100644 --- a/cpp/src/arrow/flight/sql/protocol_internal.h +++ b/cpp/src/arrow/flight/sql/protocol_internal.h @@ -23,5 +23,5 @@ #include "arrow/flight/sql/visibility.h" -#include "arrow/flight/sql/FlightSql.pb.h" // IWYU pragma: export #include "arrow/flight/Flight.pb.h" +#include "arrow/flight/sql/FlightSql.pb.h" // IWYU pragma: export diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index 5d90f63e36043..f0842381e7fef 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -774,21 +774,19 @@ Status FlightSqlServerBase::DoPut(const ServerCallContext& context, Status FlightSqlServerBase::ListActions(const ServerCallContext& context, std::vector* actions) { - *actions = { - ActionType::kCancelFlightInfo, - ActionType::kRenewFlightEndpoint, - FlightSqlServerBase::kBeginSavepointActionType, - FlightSqlServerBase::kBeginTransactionActionType, - FlightSqlServerBase::kCancelQueryActionType, - FlightSqlServerBase::kCreatePreparedStatementActionType, - FlightSqlServerBase::kCreatePreparedSubstraitPlanActionType, - FlightSqlServerBase::kClosePreparedStatementActionType, - FlightSqlServerBase::kCloseSessionActionType, - FlightSqlServerBase::kEndSavepointActionType, - FlightSqlServerBase::kEndTransactionActionType, - FlightSqlServerBase::kSetSessionOptionsActionType, - FlightSqlServerBase::kGetSessionOptionsActionType - }; + *actions = {ActionType::kCancelFlightInfo, + ActionType::kRenewFlightEndpoint, + FlightSqlServerBase::kBeginSavepointActionType, + FlightSqlServerBase::kBeginTransactionActionType, + FlightSqlServerBase::kCancelQueryActionType, + FlightSqlServerBase::kCreatePreparedStatementActionType, + FlightSqlServerBase::kCreatePreparedSubstraitPlanActionType, + FlightSqlServerBase::kClosePreparedStatementActionType, + FlightSqlServerBase::kCloseSessionActionType, + FlightSqlServerBase::kEndSavepointActionType, + FlightSqlServerBase::kEndTransactionActionType, + FlightSqlServerBase::kSetSessionOptionsActionType, + FlightSqlServerBase::kGetSessionOptionsActionType}; return Status::OK(); } @@ -1138,8 +1136,7 @@ arrow::Result FlightSqlServerBase::RenewFlightEndpoint( } arrow::Result FlightSqlServerBase::CloseSession( - const ServerCallContext& context, - const CloseSessionRequest& request) { + const ServerCallContext& context, const CloseSessionRequest& request) { return Status::NotImplemented("CloseSession not implemented"); } @@ -1174,14 +1171,12 @@ Status FlightSqlServerBase::EndTransaction(const ServerCallContext& context, } arrow::Result FlightSqlServerBase::SetSessionOptions( - const ServerCallContext& context, - const SetSessionOptionsRequest& request) { + const ServerCallContext& context, const SetSessionOptionsRequest& request) { return Status::NotImplemented("SetSessionOptions not implemented"); } arrow::Result FlightSqlServerBase::GetSessionOptions( - const ServerCallContext& context, - const GetSessionOptionsRequest& request) { + const ServerCallContext& context, const GetSessionOptionsRequest& request) { return Status::NotImplemented("GetSessionOptions not implemented"); } diff --git a/cpp/src/arrow/flight/sql/server.h b/cpp/src/arrow/flight/sql/server.h index 411106cae9c0b..9af9ce803c576 100644 --- a/cpp/src/arrow/flight/sql/server.h +++ b/cpp/src/arrow/flight/sql/server.h @@ -20,11 +20,11 @@ #pragma once +#include #include #include #include #include -#include #include #include "arrow/flight/server.h" @@ -606,22 +606,19 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlServerBase : public FlightServerBase { /// \param[in] context The call context. /// \param[in] request The session options to set. virtual arrow::Result SetSessionOptions( - const ServerCallContext& context, - const SetSessionOptionsRequest& request); + const ServerCallContext& context, const SetSessionOptionsRequest& request); /// \brief Get server session option(s). /// \param[in] context The call context. /// \param[in] request Request object. virtual arrow::Result GetSessionOptions( - const ServerCallContext& context, - const GetSessionOptionsRequest& request); + const ServerCallContext& context, const GetSessionOptionsRequest& request); /// \brief Close/invalidate the session. /// \param[in] context The call context. /// \param[in] request Request object. virtual arrow::Result CloseSession( - const ServerCallContext& context, - const CloseSessionRequest& request); + const ServerCallContext& context, const CloseSessionRequest& request); /// \brief Attempt to explicitly cancel a query. /// diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 8ce00f58a6fd9..ffe1c8619c4d4 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -15,7 +15,6 @@ // specific language governing permissions and limitations // under the License. -#include #include "arrow/flight/sql/server_session_middleware.h" #include #include @@ -56,17 +55,16 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { const std::string_view tok = s.substr(cur, len); const size_t val_pos = tok.find(pair_sep); - result.emplace_back( - tok.substr(0, val_pos), - tok.substr(val_pos + pair_sep_len, std::string::npos)); + result.emplace_back(tok.substr(0, val_pos), + tok.substr(val_pos + pair_sep_len, std::string::npos)); } return result; } public: - Status StartCall(const CallInfo &, const CallHeaders &incoming_headers, - std::shared_ptr *middleware) { + Status StartCall(const CallInfo&, const CallHeaders& incoming_headers, + std::shared_ptr* middleware) { std::string session_id; const std::pair& @@ -79,9 +77,9 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { if (cookie.first == kSessionCookieName) { session_id = cookie.second; if (session_id.empty()) - return Status::Invalid( - "Empty " + static_cast(kSessionCookieName) - + " cookie value."); + return Status::Invalid("Empty " + + static_cast(kSessionCookieName) + + " cookie value."); } } if (!session_id.empty()) break; @@ -96,12 +94,10 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { const std::shared_lock l(session_store_lock_); auto session = session_store_.at(session_id); *middleware = std::shared_ptr( - new ServerSessionMiddleware(this, incoming_headers, - session, session_id)); + new ServerSessionMiddleware(this, incoming_headers, session, session_id)); } catch (std::out_of_range& e) { - return Status::Invalid( - "Invalid or expired " - + static_cast(kSessionCookieName) + " cookie."); + return Status::Invalid("Invalid or expired " + + static_cast(kSessionCookieName) + " cookie."); } } @@ -127,42 +123,38 @@ ServerSessionMiddleware::ServerSessionMiddleware(ServerSessionMiddlewareFactory* ServerSessionMiddleware::ServerSessionMiddleware( ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, - std::shared_ptr session, - std::string session_id) - : factory_(factory), headers_(headers), session_(std::move(session)), - session_id_(std::move(session_id)), existing_session(true) {} + std::shared_ptr session, std::string session_id) + : factory_(factory), + headers_(headers), + session_(std::move(session)), + session_id_(std::move(session_id)), + existing_session(true) {} void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { if (!existing_session && session_) { addCallHeaders->AddHeader( - "set-cookie", - static_cast(kSessionCookieName) + "=" + session_id_); + "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); } } void ServerSessionMiddleware::CallCompleted(const Status&) {} -bool ServerSessionMiddleware::HasSession() const { - return static_cast(session_); -} +bool ServerSessionMiddleware::HasSession() const { return static_cast(session_); } std::shared_ptr ServerSessionMiddleware::GetSession() { - if (!session_) - session_ = factory_->GetNewSession(&session_id_); + if (!session_) session_ = factory_->GetNewSession(&session_id_); return session_; } -const CallHeaders& ServerSessionMiddleware::GetCallHeaders() const { - return headers_; -} +const CallHeaders& ServerSessionMiddleware::GetCallHeaders() const { return headers_; } std::shared_ptr MakeServerSessionMiddlewareFactory() { return std::shared_ptr( new ServerSessionMiddlewareFactory()); } -::arrow::Result -FlightSqlSession::GetSessionOption(const std::string& k) { +::arrow::Result FlightSqlSession::GetSessionOption( + const std::string& k) { const std::shared_lock l(map_lock_); try { return map_.at(k); @@ -171,8 +163,8 @@ FlightSqlSession::GetSessionOption(const std::string& k) { } } -void FlightSqlSession::SetSessionOption( - const std::string& k, const SessionOptionValue& v) { +void FlightSqlSession::SetSessionOption(const std::string& k, + const SessionOptionValue& v) { const std::unique_lock l(map_lock_); map_[k] = v; } @@ -182,6 +174,6 @@ void FlightSqlSession::EraseSessionOption(const std::string& k) { map_.erase(k); } -} // namespace sql -} // namespace flight -} // namespace arrow +} // namespace sql +} // namespace flight +} // namespace arrow diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 84c7b3bb9bb78..e03dd23e6b1c3 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -21,6 +21,7 @@ #pragma once #include +#include #include "arrow/flight/server_middleware.h" #include "arrow/flight/sql/types.h" @@ -31,13 +32,13 @@ namespace sql { class ServerSessionMiddlewareFactory; -static constexpr char const kSessionCookieName[] = - "flight_sql_session_id"; +static constexpr char const kSessionCookieName[] = "flight_sql_session_id"; class FlightSqlSession { protected: std::map map_; std::shared_mutex map_lock_; + public: /// \brief Get session option by key ::arrow::Result GetSessionOption(const std::string&); @@ -48,8 +49,7 @@ class FlightSqlSession { }; /// \brief A middleware to handle Session option persistence and related *Cookie headers. -class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware - : public ServerMiddleware { +class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware { public: static constexpr char const kMiddlewareName[] = "arrow::flight::sql::ServerSessionMiddleware"; @@ -66,25 +66,22 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware const CallHeaders& GetCallHeaders() const; protected: - friend class ServerSessionMiddlewareFactory; + friend class ServerSessionMiddlewareFactory; ServerSessionMiddlewareFactory* factory_; const CallHeaders& headers_; std::shared_ptr session_; std::string session_id_; const bool existing_session; - ServerSessionMiddleware(ServerSessionMiddlewareFactory*, - const CallHeaders&); - ServerSessionMiddleware(ServerSessionMiddlewareFactory*, - const CallHeaders&, - std::shared_ptr, - std::string session_id); + ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders&); + ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders&, + std::shared_ptr, std::string session_id); }; /// \brief Returns a ServerMiddlewareFactory that handles Session option storage. ARROW_FLIGHT_SQL_EXPORT std::shared_ptr MakeServerSessionMiddlewareFactory(); -} // namespace sql -} // namespace flight -} // namespace arrow +} // namespace sql +} // namespace flight +} // namespace arrow diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index c49f52d42794a..56d92394cc17c 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -515,31 +515,30 @@ std::ostream& operator<<(std::ostream& os, std::map m) { } namespace { - static bool CompareSessionOptionMaps( - const std::map& a, - const std::map& b) { - if (a.size() != b.size()) { +static bool CompareSessionOptionMaps(const std::map& a, + const std::map& b) { + if (a.size() != b.size()) { + return false; + } + for (const auto& [k, v] : a) { + if (!b.count(k)) { return false; } - for (const auto & [k, v] : a) { - if (!b.count(k)) { + try { + const auto& b_v = b.at(k); + if (v.index() != b_v.index()) { return false; } - try { - const auto& b_v = b.at(k); - if (v.index() != b_v.index()) { - return false; - } - if (v != b_v) { - return false; - } - } catch ( const std::out_of_range& e ) { + if (v != b_v) { return false; } + } catch (const std::out_of_range& e) { + return false; } - return true; } -} // namespace + return true; +} +} // namespace // SetSessionOptionsRequest @@ -555,8 +554,7 @@ bool SetSessionOptionsRequest::Equals(const SetSessionOptionsRequest& other) con return CompareSessionOptionMaps(session_options, other.session_options); } -arrow::Result -SetSessionOptionsRequest::SerializeToString() const { +arrow::Result SetSessionOptionsRequest::SerializeToString() const { pb::SetSessionOptionsRequest pb_request; RETURN_NOT_OK(internal::ToProto(*this, &pb_request)); @@ -567,8 +565,8 @@ SetSessionOptionsRequest::SerializeToString() const { return out; } -arrow::Result -SetSessionOptionsRequest::Deserialize(std::string_view serialized) { +arrow::Result SetSessionOptionsRequest::Deserialize( + std::string_view serialized) { // TODO these & SerializeToString should all be factored out to a superclass pb::SetSessionOptionsRequest pb_request; if (serialized.size() > static_cast(std::numeric_limits::max())) { @@ -602,8 +600,7 @@ bool SetSessionOptionsResult::Equals(const SetSessionOptionsResult& other) const return true; } -arrow::Result -SetSessionOptionsResult::SerializeToString() const { +arrow::Result SetSessionOptionsResult::SerializeToString() const { pb::SetSessionOptionsResult pb_result; RETURN_NOT_OK(internal::ToProto(*this, &pb_result)); @@ -614,8 +611,8 @@ SetSessionOptionsResult::SerializeToString() const { return out; } -arrow::Result -SetSessionOptionsResult::Deserialize(std::string_view serialized) { +arrow::Result SetSessionOptionsResult::Deserialize( + std::string_view serialized) { pb::SetSessionOptionsResult pb_result; if (serialized.size() > static_cast(std::numeric_limits::max())) { return Status::Invalid( @@ -641,8 +638,7 @@ bool GetSessionOptionsRequest::Equals(const GetSessionOptionsRequest& other) con return true; } -arrow::Result -GetSessionOptionsRequest::SerializeToString() const { +arrow::Result GetSessionOptionsRequest::SerializeToString() const { pb::GetSessionOptionsRequest pb_request; RETURN_NOT_OK(internal::ToProto(*this, &pb_request)); @@ -653,8 +649,8 @@ GetSessionOptionsRequest::SerializeToString() const { return out; } -arrow::Result -GetSessionOptionsRequest::Deserialize(std::string_view serialized) { +arrow::Result GetSessionOptionsRequest::Deserialize( + std::string_view serialized) { pb::GetSessionOptionsRequest pb_request; if (serialized.size() > static_cast(std::numeric_limits::max())) { return Status::Invalid( @@ -684,8 +680,7 @@ bool GetSessionOptionsResult::Equals(const GetSessionOptionsResult& other) const return CompareSessionOptionMaps(session_options, other.session_options); } -arrow::Result -GetSessionOptionsResult::SerializeToString() const { +arrow::Result GetSessionOptionsResult::SerializeToString() const { pb::GetSessionOptionsResult pb_result; RETURN_NOT_OK(internal::ToProto(*this, &pb_result)); @@ -696,8 +691,8 @@ GetSessionOptionsResult::SerializeToString() const { return out; } -arrow::Result -GetSessionOptionsResult::Deserialize(std::string_view serialized) { +arrow::Result GetSessionOptionsResult::Deserialize( + std::string_view serialized) { pb::GetSessionOptionsResult pb_result; if (serialized.size() > static_cast(std::numeric_limits::max())) { return Status::Invalid( @@ -715,16 +710,11 @@ GetSessionOptionsResult::Deserialize(std::string_view serialized) { // CloseSessionRequest -std::string CloseSessionRequest::ToString() const { - return ""; -} +std::string CloseSessionRequest::ToString() const { return ""; } -bool CloseSessionRequest::Equals(const CloseSessionRequest& other) const { - return true; -} +bool CloseSessionRequest::Equals(const CloseSessionRequest& other) const { return true; } -arrow::Result -CloseSessionRequest::SerializeToString() const { +arrow::Result CloseSessionRequest::SerializeToString() const { pb::CloseSessionRequest pb_request; RETURN_NOT_OK(internal::ToProto(*this, &pb_request)); @@ -735,12 +725,11 @@ CloseSessionRequest::SerializeToString() const { return out; } -arrow::Result -CloseSessionRequest::Deserialize(std::string_view serialized) { +arrow::Result CloseSessionRequest::Deserialize( + std::string_view serialized) { pb::CloseSessionRequest pb_request; if (serialized.size() > static_cast(std::numeric_limits::max())) { - return Status::Invalid( - "Serialized CloseSessionRequest size should not exceed 2 GiB"); + return Status::Invalid("Serialized CloseSessionRequest size should not exceed 2 GiB"); } google::protobuf::io::ArrayInputStream input(serialized.data(), static_cast(serialized.size())); @@ -763,14 +752,13 @@ std::string CloseSessionResult::ToString() const { } bool CloseSessionResult::Equals(const CloseSessionResult& other) const { - if (status != other.status) { + if (status != other.status) { return false; } return true; } -arrow::Result -CloseSessionResult::SerializeToString() const { +arrow::Result CloseSessionResult::SerializeToString() const { pb::CloseSessionResult pb_result; RETURN_NOT_OK(internal::ToProto(*this, &pb_result)); @@ -781,12 +769,11 @@ CloseSessionResult::SerializeToString() const { return out; } -arrow::Result -CloseSessionResult::Deserialize(std::string_view serialized) { +arrow::Result CloseSessionResult::Deserialize( + std::string_view serialized) { pb::CloseSessionResult pb_result; if (serialized.size() > static_cast(std::numeric_limits::max())) { - return Status::Invalid( - "Serialized CloseSessionResult size should not exceed 2 GiB"); + return Status::Invalid("Serialized CloseSessionResult size should not exceed 2 GiB"); } google::protobuf::io::ArrayInputStream input(serialized.data(), static_cast(serialized.size())); @@ -974,26 +961,20 @@ const ActionType ActionType::kRenewFlightEndpoint = "Request Message: RenewFlightEndpointRequest\n" "Response Message: Renewed FlightEndpoint"}; const ActionType ActionType::kSetSessionOptions = - ActionType{ - "SetSessionOptions", - "Set client session options by key/value pairs.\n" - "Request Message: SetSessionOptionsRequest\n" - "Response Message: SetSessionOptionsResult\n" - }; + ActionType{"SetSessionOptions", + "Set client session options by key/value pairs.\n" + "Request Message: SetSessionOptionsRequest\n" + "Response Message: SetSessionOptionsResult\n"}; const ActionType ActionType::kGetSessionOptions = - ActionType{ - "GetSessionOptions", - "Get current client session options\n" - "Request Message: GetSessionOptionsRequest\n" - "Response Message: GetSessionOptionsResult\n" - }; + ActionType{"GetSessionOptions", + "Get current client session options\n" + "Request Message: GetSessionOptionsRequest\n" + "Response Message: GetSessionOptionsResult\n"}; const ActionType ActionType::kCloseSession = - ActionType{ - "CloseSession", - "Explicitly close/invalidate the cookie-specified client session.\n" - "Request Message: CloseSessionRequest\n" - "Response Message: CloseSessionResult\n" - }; + ActionType{"CloseSession", + "Explicitly close/invalidate the cookie-specified client session.\n" + "Request Message: CloseSessionRequest\n" + "Response Message: CloseSessionResult\n"}; bool ActionType::Equals(const ActionType& other) const { return type == other.type && description == other.description; diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 885accc98e42d..384d58e895c9f 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -765,8 +765,8 @@ struct ARROW_FLIGHT_EXPORT CancelFlightInfoRequest { }; /// \brief Variant supporting all possible value types for {Set,Get}SessionOptions -using SessionOptionValue = std::variant< - std::string, bool, int32_t, int64_t, float, double, std::vector>; +using SessionOptionValue = std::variant>; /// \brief The result of setting a session option. enum class SetSessionOptionStatus : int8_t { @@ -780,29 +780,13 @@ enum class SetSessionOptionStatus : int8_t { std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& r); /// \brief The result of closing a session. -enum class CloseSessionStatus : int8_t { - kUnspecified, - kClosed, - kClosing, - kNotClosable -}; +enum class CloseSessionStatus : int8_t { kUnspecified, kClosed, kClosing, kNotClosable }; std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& r); static const char* const SetSessionOptionStatusNames[] = { - "Unspecified", - "Ok", - "OkMapped", - "InvalidKey", - "InvalidValue", - "Error" -}; -static const char* const CloseSessionStatusNames[] = { - "Unspecified", - "Closed", - "Closing", - "NotClosable" -}; - + "Unspecified", "Ok", "OkMapped", "InvalidKey", "InvalidValue", "Error"}; +static const char* const CloseSessionStatusNames[] = {"Unspecified", "Closed", "Closing", + "NotClosable"}; /// \brief A request to set a set of session options by key/value. struct ARROW_FLIGHT_EXPORT SetSessionOptionsRequest { @@ -824,8 +808,7 @@ struct ARROW_FLIGHT_EXPORT SetSessionOptionsRequest { arrow::Result SerializeToString() const; /// \brief Deserialize this message from its wire-format representation. - static arrow::Result - Deserialize(std::string_view serialized); + static arrow::Result Deserialize(std::string_view serialized); }; /// \brief The result(s) of setting session option(s). @@ -848,8 +831,7 @@ struct ARROW_FLIGHT_EXPORT SetSessionOptionsResult { arrow::Result SerializeToString() const; /// \brief Deserialize this message from its wire-format representation. - static arrow::Result - Deserialize(std::string_view serialized); + static arrow::Result Deserialize(std::string_view serialized); }; /// \brief A request to get current session options. @@ -870,8 +852,7 @@ struct ARROW_FLIGHT_EXPORT GetSessionOptionsRequest { arrow::Result SerializeToString() const; /// \brief Deserialize this message from its wire-format representation. - static arrow::Result - Deserialize(std::string_view serialized); + static arrow::Result Deserialize(std::string_view serialized); }; /// \brief The current session options. @@ -894,12 +875,12 @@ struct ARROW_FLIGHT_EXPORT GetSessionOptionsResult { arrow::Result SerializeToString() const; /// \brief Deserialize this message from its wire-format representation. - static arrow::Result - Deserialize(std::string_view serialized); + static arrow::Result Deserialize(std::string_view serialized); }; /// \brief A request to close the open client session. -struct ARROW_FLIGHT_EXPORT CloseSessionRequest { std::string ToString() const; +struct ARROW_FLIGHT_EXPORT CloseSessionRequest { + std::string ToString() const; bool Equals(const CloseSessionRequest& other) const; friend bool operator==(const CloseSessionRequest& left, @@ -915,8 +896,7 @@ struct ARROW_FLIGHT_EXPORT CloseSessionRequest { std::string ToString() const; arrow::Result SerializeToString() const; /// \brief Deserialize this message from its wire-format representation. - static arrow::Result - Deserialize(std::string_view serialized); + static arrow::Result Deserialize(std::string_view serialized); }; /// \brief The result of attempting to close the client session. @@ -939,8 +919,7 @@ struct ARROW_FLIGHT_EXPORT CloseSessionResult { arrow::Result SerializeToString() const; /// \brief Deserialize this message from its wire-format representation. - static arrow::Result - Deserialize(std::string_view serialized); + static arrow::Result Deserialize(std::string_view serialized); }; /// \brief An iterator to FlightInfo instances returned by ListFlights. diff --git a/cpp/src/arrow/json/test_common.h b/cpp/src/arrow/json/test_common.h index 2f819779bdb59..423a0123c0586 100644 --- a/cpp/src/arrow/json/test_common.h +++ b/cpp/src/arrow/json/test_common.h @@ -89,7 +89,7 @@ struct GenerateImpl { Status Visit(const NullType&) { return OK(writer.Null()); } Status Visit(const BooleanType&) { - return OK(writer.Bool(std::uniform_int_distribution{}(e)&1)); + return OK(writer.Bool(std::uniform_int_distribution{}(e) & 1)); } template diff --git a/cpp/src/arrow/util/tracing_internal.h b/cpp/src/arrow/util/tracing_internal.h index a031edf08dc77..46d3ba89514f9 100644 --- a/cpp/src/arrow/util/tracing_internal.h +++ b/cpp/src/arrow/util/tracing_internal.h @@ -135,12 +135,11 @@ opentelemetry::nostd::shared_ptr& RewrapSpan( opentelemetry::trace::StartSpanOptions SpanOptionsWithParent( const util::tracing::Span& parent_span); -#define START_SPAN(target_span, ...) \ - auto opentelemetry_scope##__LINE__ = \ - ::arrow::internal::tracing::GetTracer()->WithActiveSpan( \ - ::arrow::internal::tracing::RewrapSpan( \ - target_span.details.get(), \ - ::arrow::internal::tracing::GetTracer()->StartSpan(__VA_ARGS__))) +#define START_SPAN(target_span, ...) \ + auto opentelemetry_scope##__LINE__ = ::arrow::internal::tracing::GetTracer() \ + -> WithActiveSpan(::arrow::internal::tracing::RewrapSpan( \ + target_span.details.get(), \ + ::arrow::internal::tracing::GetTracer()->StartSpan(__VA_ARGS__))) #define START_SCOPED_SPAN(target_span, ...) \ ::arrow::internal::tracing::Scope( \ diff --git a/cpp/src/gandiva/gdv_hash_function_stubs.cc b/cpp/src/gandiva/gdv_hash_function_stubs.cc index aac70a06be6c7..84f30e941406a 100644 --- a/cpp/src/gandiva/gdv_hash_function_stubs.cc +++ b/cpp/src/gandiva/gdv_hash_function_stubs.cc @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -//#pragma once +// #pragma once #include "gandiva/engine.h" #include "gandiva/exported_funcs.h" diff --git a/cpp/src/gandiva/precompiled/string_ops_test.cc b/cpp/src/gandiva/precompiled/string_ops_test.cc index 89213592e7ea2..45338739111d6 100644 --- a/cpp/src/gandiva/precompiled/string_ops_test.cc +++ b/cpp/src/gandiva/precompiled/string_ops_test.cc @@ -101,15 +101,15 @@ TEST(TestStringOps, TestChrBigInt) { out = chr_int64(ctx_ptr, -66, &out_len); EXPECT_EQ(std::string(out, out_len), "\xBE"); - //€ + // € out = chr_int32(ctx_ptr, 128, &out_len); EXPECT_EQ(std::string(out, out_len), "\x80"); - //œ + // œ out = chr_int64(ctx_ptr, 156, &out_len); EXPECT_EQ(std::string(out, out_len), "\x9C"); - //ÿ + // ÿ out = chr_int32(ctx_ptr, 255, &out_len); EXPECT_EQ(std::string(out, out_len), "\xFF"); From 1eaf15a85630c2876de0c5c9b21d52a8c177468f Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 2 Nov 2023 16:45:03 -0700 Subject: [PATCH 047/195] [builds] Add missing include --- cpp/src/arrow/flight/types.h | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 384d58e895c9f..233132e9dbda6 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "arrow/flight/type_fwd.h" From 6a53fbaf52f114344776b475560cc8c4f970c9f2 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 2 Nov 2023 17:20:41 -0700 Subject: [PATCH 048/195] [builds] Fix clang-format{14,17} differences --- cpp/src/arrow/flight/sql/server_session_middleware.h | 2 +- cpp/src/arrow/json/test_common.h | 2 +- cpp/src/arrow/util/tracing_internal.h | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index e03dd23e6b1c3..eb7963a14d917 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -20,8 +20,8 @@ #pragma once -#include #include +#include #include "arrow/flight/server_middleware.h" #include "arrow/flight/sql/types.h" diff --git a/cpp/src/arrow/json/test_common.h b/cpp/src/arrow/json/test_common.h index 423a0123c0586..2f819779bdb59 100644 --- a/cpp/src/arrow/json/test_common.h +++ b/cpp/src/arrow/json/test_common.h @@ -89,7 +89,7 @@ struct GenerateImpl { Status Visit(const NullType&) { return OK(writer.Null()); } Status Visit(const BooleanType&) { - return OK(writer.Bool(std::uniform_int_distribution{}(e) & 1)); + return OK(writer.Bool(std::uniform_int_distribution{}(e)&1)); } template diff --git a/cpp/src/arrow/util/tracing_internal.h b/cpp/src/arrow/util/tracing_internal.h index 46d3ba89514f9..a031edf08dc77 100644 --- a/cpp/src/arrow/util/tracing_internal.h +++ b/cpp/src/arrow/util/tracing_internal.h @@ -135,11 +135,12 @@ opentelemetry::nostd::shared_ptr& RewrapSpan( opentelemetry::trace::StartSpanOptions SpanOptionsWithParent( const util::tracing::Span& parent_span); -#define START_SPAN(target_span, ...) \ - auto opentelemetry_scope##__LINE__ = ::arrow::internal::tracing::GetTracer() \ - -> WithActiveSpan(::arrow::internal::tracing::RewrapSpan( \ - target_span.details.get(), \ - ::arrow::internal::tracing::GetTracer()->StartSpan(__VA_ARGS__))) +#define START_SPAN(target_span, ...) \ + auto opentelemetry_scope##__LINE__ = \ + ::arrow::internal::tracing::GetTracer()->WithActiveSpan( \ + ::arrow::internal::tracing::RewrapSpan( \ + target_span.details.get(), \ + ::arrow::internal::tracing::GetTracer()->StartSpan(__VA_ARGS__))) #define START_SCOPED_SPAN(target_span, ...) \ ::arrow::internal::tracing::Scope( \ From 91c9e1705bea56f66d45a50cbfb0f4ec080ce0cf Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 2 Nov 2023 18:09:00 -0700 Subject: [PATCH 049/195] [builds] Add missed change from previous --- cpp/src/arrow/flight/serialization_internal.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 0fd14c5037620..326a4b478958c 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -33,7 +33,7 @@ struct overloaded : Ts... { using Ts::operator()...; }; template // CTAD will not be needed for >=C++20 -overloaded(Ts...) -> overloaded; +overloaded(Ts...)->overloaded; namespace arrow { namespace flight { From 16d850626051e51434af5a07b3f17c5973ead2fb Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 2 Nov 2023 18:50:00 -0700 Subject: [PATCH 050/195] [builds] C++ docs fixup --- cpp/src/arrow/flight/client.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/src/arrow/flight/client.h b/cpp/src/arrow/flight/client.h index 68ba73a8cea9d..3ac6f0c840d0a 100644 --- a/cpp/src/arrow/flight/client.h +++ b/cpp/src/arrow/flight/client.h @@ -393,12 +393,14 @@ class ARROW_FLIGHT_EXPORT FlightClient { /// \\brief Get the current server session options. The session is generally /// accessed via an HTTP cookie. /// \param[in] options Per-RPC options + /// \param[in] request The GetSessionOptions request object. ::arrow::Result GetSessionOptions( const FlightCallOptions& options, const GetSessionOptionsRequest& request); /// \\brief Close/invalidate the current server session. The session is generally /// accessed via an HTTP cookie. /// \param[in] options Per-RPC options + /// \param[in] request The CloseSession request object. ::arrow::Result CloseSession(const FlightCallOptions& options, const CloseSessionRequest& request); From 3f4b6a22a151681cdaa60eb59d298a0e8c1e0567 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 3 Nov 2023 16:28:04 -0700 Subject: [PATCH 051/195] Add Protobuf docstrings & rename Flight session cookie --- .../flight/sql/server_session_middleware.h | 2 +- format/Flight.proto | 94 ++++++++++--------- 2 files changed, 50 insertions(+), 46 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index eb7963a14d917..7cef409eaecbd 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -32,7 +32,7 @@ namespace sql { class ServerSessionMiddlewareFactory; -static constexpr char const kSessionCookieName[] = "flight_sql_session_id"; +static constexpr char const kSessionCookieName[] = "arrow_flight_session_id"; class FlightSqlSession { protected: diff --git a/format/Flight.proto b/format/Flight.proto index 614129de12a5a..94bc670086d41 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -528,44 +528,9 @@ message PutResult { } /* - * Request message for the "Close Session" action. - * - * The exiting session is referenced via a cookie header. - */ -message CloseSessionRequest { - option (experimental) = true; -} - -/* - * The result of closing a session. - * - * The result should be wrapped in a google.protobuf.Any message. + * EXPERIMENTAL: Union of possible value types for a Session Option to be set to. */ -message CloseSessionResult { - option (experimental) = true; - - enum Status { - // The session close status is unknown. Servers should avoid using - // this value (send a NOT_FOUND error if the requested query is - // not known). Clients can retry the request. - CLOSE_RESULT_UNSPECIFIED = 0; - // The session close request is complete. Subsequent requests with - // a NOT_FOUND error. - CLOSE_RESULT_CLOSED = 1; - // The session close request is in progress. The client may retry - // the close request. - CLOSE_RESULT_CLOSING = 2; - // The session is not closeable. The client should not retry the - // close request. - CLOSE_RESULT_NOT_CLOSEABLE = 3; - } - - Status status = 1; -} - message SessionOptionValue { - option (experimental) = true; - message StringListValue { repeated string values = 1; } @@ -581,15 +546,21 @@ message SessionOptionValue { } } +/* + * EXPERIMENTAL: A request to set session options for an existing or new (implicit) + * server session. + * + * Sessions are persisted and referenced via RFC 6265 HTTP cookies, canonically + * 'arrow_flight_session_id', although implementations may freely choose their own name. + */ message SetSessionOptionsRequest { - option (experimental) = true; - map session_options = 1; } +/* + * EXPERIMENTAL: The results (individually) of setting a set of session options. + */ message SetSessionOptionsResult { - option (experimental) = true; - enum Status { // The status of setting the option is unknown. Servers should avoid using // this value (send a NOT_FOUND error if the requested query is @@ -610,16 +581,49 @@ message SetSessionOptionsResult { map statuses = 1; } +/* + * EXPERIMENTAL: A request to access the session options for the current server session. + * + * The existing session is referenced via a cookie header; it is an error to make this + * request with a missing, invalid, or expired session cookie header. + */ message GetSessionOptionsRequest { - option (experimental) = true; } +/* + * EXPERIMENTAL: The result containing the current server session options. + */ message GetSessionOptionsResult { - option (experimental) = true; - map session_options = 1; } -extend google.protobuf.MessageOptions { - bool experimental = 1000; +/* + * Request message for the "Close Session" action. + * + * The exiting session is referenced via a cookie header. + */ +message CloseSessionRequest { +} + +/* + * The result of closing a session. + */ +message CloseSessionResult { + enum Status { + // The session close status is unknown. Servers should avoid using + // this value (send a NOT_FOUND error if the requested query is + // not known). Clients can retry the request. + CLOSE_RESULT_UNSPECIFIED = 0; + // The session close request is complete. Subsequent requests with + // a NOT_FOUND error. + CLOSE_RESULT_CLOSED = 1; + // The session close request is in progress. The client may retry + // the close request. + CLOSE_RESULT_CLOSING = 2; + // The session is not closeable. The client should not retry the + // close request. + CLOSE_RESULT_NOT_CLOSEABLE = 3; + } + + Status status = 1; } From d0f383cfab72c405c74a1fea482b2aedfaefb897 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 3 Nov 2023 16:30:12 -0700 Subject: [PATCH 052/195] [builds] Remove unused Proto import --- format/Flight.proto | 1 - 1 file changed, 1 deletion(-) diff --git a/format/Flight.proto b/format/Flight.proto index 94bc670086d41..046c3765e7074 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -18,7 +18,6 @@ syntax = "proto3"; import "google/protobuf/timestamp.proto"; -import "google/protobuf/descriptor.proto"; option java_package = "org.apache.arrow.flight.impl"; option go_package = "github.com/apache/arrow/go/arrow/flight/gen/flight"; From 29d12ddcc8a750acf4fb3e2b85c8bc273a088d54 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 9 Nov 2023 13:46:33 -0800 Subject: [PATCH 053/195] Fixes for @stevelorddremio's feedback --- format/Flight.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/format/Flight.proto b/format/Flight.proto index 046c3765e7074..95703dc400f8d 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -571,9 +571,9 @@ message SetSessionOptionsResult { SET_SESSION_OPTION_RESULT_OK_MAPPED = 2; // The given session option name is invalid. SET_SESSION_OPTION_RESULT_INVALID_NAME = 3; - // The session cannot be set to the given value. + // The session name is invalid or unsupported by the server. SET_SESSION_OPTION_RESULT_INVALID_VALUE = 4; - // The session cannot be set. + // The session option cannot be set. SET_SESSION_OPTION_RESULT_ERROR = 5; } @@ -614,7 +614,7 @@ message CloseSessionResult { // not known). Clients can retry the request. CLOSE_RESULT_UNSPECIFIED = 0; // The session close request is complete. Subsequent requests with - // a NOT_FOUND error. + // the same session produce a NOT_FOUND error. CLOSE_RESULT_CLOSED = 1; // The session close request is in progress. The client may retry // the close request. From cbe3478e0653d686ee1c6ec4a64d5d73b1740182 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 9 Nov 2023 14:39:05 -0800 Subject: [PATCH 054/195] Revert extraneous linter changes --- cpp/src/gandiva/gdv_hash_function_stubs.cc | 2 +- cpp/src/gandiva/precompiled/string_ops_test.cc | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/src/gandiva/gdv_hash_function_stubs.cc b/cpp/src/gandiva/gdv_hash_function_stubs.cc index 84f30e941406a..aac70a06be6c7 100644 --- a/cpp/src/gandiva/gdv_hash_function_stubs.cc +++ b/cpp/src/gandiva/gdv_hash_function_stubs.cc @@ -15,7 +15,7 @@ // specific language governing permissions and limitations // under the License. -// #pragma once +//#pragma once #include "gandiva/engine.h" #include "gandiva/exported_funcs.h" diff --git a/cpp/src/gandiva/precompiled/string_ops_test.cc b/cpp/src/gandiva/precompiled/string_ops_test.cc index 45338739111d6..89213592e7ea2 100644 --- a/cpp/src/gandiva/precompiled/string_ops_test.cc +++ b/cpp/src/gandiva/precompiled/string_ops_test.cc @@ -101,15 +101,15 @@ TEST(TestStringOps, TestChrBigInt) { out = chr_int64(ctx_ptr, -66, &out_len); EXPECT_EQ(std::string(out, out_len), "\xBE"); - // € + //€ out = chr_int32(ctx_ptr, 128, &out_len); EXPECT_EQ(std::string(out, out_len), "\x80"); - // œ + //œ out = chr_int64(ctx_ptr, 156, &out_len); EXPECT_EQ(std::string(out, out_len), "\x9C"); - // ÿ + //ÿ out = chr_int32(ctx_ptr, 255, &out_len); EXPECT_EQ(std::string(out, out_len), "\xFF"); From f391ea955a47d93148dc89dd62c440fcdf4d13ed Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 9 Nov 2023 15:30:34 -0800 Subject: [PATCH 055/195] More PR feedback resolution --- cpp/src/arrow/flight/client.h | 4 ++-- cpp/src/arrow/flight/sql/client.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/client.h b/cpp/src/arrow/flight/client.h index 3ac6f0c840d0a..68fa0ff67d040 100644 --- a/cpp/src/arrow/flight/client.h +++ b/cpp/src/arrow/flight/client.h @@ -393,14 +393,14 @@ class ARROW_FLIGHT_EXPORT FlightClient { /// \\brief Get the current server session options. The session is generally /// accessed via an HTTP cookie. /// \param[in] options Per-RPC options - /// \param[in] request The GetSessionOptions request object. + /// \param[in] request The (empty) GetSessionOptions request object. ::arrow::Result GetSessionOptions( const FlightCallOptions& options, const GetSessionOptionsRequest& request); /// \\brief Close/invalidate the current server session. The session is generally /// accessed via an HTTP cookie. /// \param[in] options Per-RPC options - /// \param[in] request The CloseSession request object. + /// \param[in] request The (empty) CloseSession request object. ::arrow::Result CloseSession(const FlightCallOptions& options, const CloseSessionRequest& request); diff --git a/cpp/src/arrow/flight/sql/client.h b/cpp/src/arrow/flight/sql/client.h index 19cd2801bdd2e..01820e9ec85fb 100644 --- a/cpp/src/arrow/flight/sql/client.h +++ b/cpp/src/arrow/flight/sql/client.h @@ -363,6 +363,7 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlClient { /// \brief Gets current session options. /// /// \param[in] options RPC-layer hints for this call. + /// \param[in] request The (empty) GetSessionOptions request object. ::arrow::Result GetSessionOptions( const FlightCallOptions& options, const GetSessionOptionsRequest& request) { return impl_->GetSessionOptions(options, request); @@ -371,6 +372,7 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlClient { /// \brief Explicitly closes the session if applicable. /// /// \param[in] options RPC-layer hints for this call. + /// \param[in] request The (empty) CloseSession request object. ::arrow::Result CloseSession(const FlightCallOptions& options, const CloseSessionRequest& request) { return impl_->CloseSession(options, request); From df0652b574890efb6b462cb9002e9566bf751f96 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 9 Nov 2023 16:04:56 -0800 Subject: [PATCH 056/195] More PR feedback --- cpp/src/arrow/flight/client.cc | 2 -- cpp/src/arrow/flight/sql/client.h | 1 - cpp/src/arrow/flight/sql/server_session_middleware.cc | 4 ++++ 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/client.cc b/cpp/src/arrow/flight/client.cc index b096ec470763b..4d4f13a09fb26 100644 --- a/cpp/src/arrow/flight/client.cc +++ b/cpp/src/arrow/flight/client.cc @@ -716,7 +716,6 @@ arrow::Result FlightClient::DoExchange( ::arrow::Result FlightClient::SetSessionOptions( const FlightCallOptions& options, const SetSessionOptionsRequest& request) { RETURN_NOT_OK(CheckOpen()); - RETURN_NOT_OK(CheckOpen()); ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); Action action{ActionType::kSetSessionOptions.type, Buffer::FromString(body)}; ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); @@ -731,7 +730,6 @@ ::arrow::Result FlightClient::SetSessionOptions( ::arrow::Result FlightClient::GetSessionOptions( const FlightCallOptions& options, const GetSessionOptionsRequest& request) { RETURN_NOT_OK(CheckOpen()); - RETURN_NOT_OK(CheckOpen()); ARROW_ASSIGN_OR_RAISE(auto body, request.SerializeToString()); Action action{ActionType::kGetSessionOptions.type, Buffer::FromString(body)}; ARROW_ASSIGN_OR_RAISE(auto stream, DoAction(options, action)); diff --git a/cpp/src/arrow/flight/sql/client.h b/cpp/src/arrow/flight/sql/client.h index 01820e9ec85fb..9782611dbadcd 100644 --- a/cpp/src/arrow/flight/sql/client.h +++ b/cpp/src/arrow/flight/sql/client.h @@ -18,7 +18,6 @@ #pragma once #include -#include #include #include diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index ffe1c8619c4d4..d41d39247e286 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -55,6 +55,10 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { const std::string_view tok = s.substr(cur, len); const size_t val_pos = tok.find(pair_sep); + if (val_pos == std::string::npos) { + // The cookie header is somewhat malformed; ignore the key and continue parsing + continue; + } result.emplace_back(tok.substr(0, val_pos), tok.substr(val_pos + pair_sep_len, std::string::npos)); } From ad6ffd3c585e932e5236dfa9535304f54974ea23 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 9 Nov 2023 16:29:47 -0800 Subject: [PATCH 057/195] More PR feedback --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index d41d39247e286..beb5c848496f3 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -79,11 +79,11 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { ParseCookieString(cookie_header); for (const std::pair& cookie : cookies) { if (cookie.first == kSessionCookieName) { - session_id = cookie.second; - if (session_id.empty()) + if (cookie.second.empty()) return Status::Invalid("Empty " + static_cast(kSessionCookieName) + " cookie value."); + session_id = std::move(cookie.second); } } if (!session_id.empty()) break; From 14ee82d1bc39e744105bd7262aab20a73b2888a6 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 9 Nov 2023 17:10:18 -0800 Subject: [PATCH 058/195] [builds] More PR fixups --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index beb5c848496f3..0212c9aee07ef 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -21,6 +21,8 @@ #include #include +using namespace std::string_literals; + namespace arrow { namespace flight { namespace sql { @@ -80,7 +82,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { for (const std::pair& cookie : cookies) { if (cookie.first == kSessionCookieName) { if (cookie.second.empty()) - return Status::Invalid("Empty " + + return Status::Invalid("Empty "s + static_cast(kSessionCookieName) + " cookie value."); session_id = std::move(cookie.second); From c54192487ebde28ec56dcc9c86b349e77b8c3c59 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 9 Nov 2023 17:13:50 -0800 Subject: [PATCH 059/195] PR feedback --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 0212c9aee07ef..844d6f0f51a54 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -136,9 +136,9 @@ ServerSessionMiddleware::ServerSessionMiddleware( session_id_(std::move(session_id)), existing_session(true) {} -void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* addCallHeaders) { +void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* add_call_headers) { if (!existing_session && session_) { - addCallHeaders->AddHeader( + add_call_headers->AddHeader( "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); } } From 98e22347481dd11c0cdca222ca9f91b2486bffe8 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 9 Nov 2023 17:24:02 -0800 Subject: [PATCH 060/195] PR feedback --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 844d6f0f51a54..26eb235957f7a 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -82,9 +82,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { for (const std::pair& cookie : cookies) { if (cookie.first == kSessionCookieName) { if (cookie.second.empty()) - return Status::Invalid("Empty "s + - static_cast(kSessionCookieName) + - " cookie value."); + return Status::Invalid("Empty "s + kSessionCookieName + " cookie value."); session_id = std::move(cookie.second); } } @@ -102,8 +100,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { *middleware = std::shared_ptr( new ServerSessionMiddleware(this, incoming_headers, session, session_id)); } catch (std::out_of_range& e) { - return Status::Invalid("Invalid or expired " + - static_cast(kSessionCookieName) + " cookie."); + return Status::Invalid("Invalid or expired "s + kSessionCookieName + " cookie."); } } From 345c2be24c005c5987d526af65a628eb3fe3ca93 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 9 Nov 2023 17:33:49 -0800 Subject: [PATCH 061/195] PR feedback --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 26eb235957f7a..31f5e10c18231 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -91,7 +91,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { if (session_id.empty()) { // No cookie was found - *middleware = std::shared_ptr( + *middleware = std::shared_ptr( // PHOXME needs to be properly pimpl w/ public constructor to make_shared (then fix that) new ServerSessionMiddleware(this, incoming_headers)); } else { try { @@ -152,8 +152,7 @@ std::shared_ptr ServerSessionMiddleware::GetSession() { const CallHeaders& ServerSessionMiddleware::GetCallHeaders() const { return headers_; } std::shared_ptr MakeServerSessionMiddlewareFactory() { - return std::shared_ptr( - new ServerSessionMiddlewareFactory()); + return std::make_shared(); } ::arrow::Result FlightSqlSession::GetSessionOption( From 45e1f7c5a634c37d34705d17dcf1d715c43c560a Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 10 Nov 2023 12:02:14 -0800 Subject: [PATCH 062/195] Refactor to facilitate proper make_shared --- .../flight/sql/server_session_middleware.cc | 114 ++++++++++-------- .../flight/sql/server_session_middleware.h | 26 ++-- 2 files changed, 74 insertions(+), 66 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 31f5e10c18231..98ca9d7b24234 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -35,6 +35,59 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { boost::uuids::random_generator uuid_generator_; std::vector> ParseCookieString( + const std::string_view& s); + + public: + Status StartCall(const CallInfo&, const CallHeaders& incoming_headers, + std::shared_ptr* middleware); + + /// \brief Get a new, empty session option map and its id key. + std::shared_ptr GetNewSession(std::string* session_id); +}; + +class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { + protected: + ServerSessionMiddlewareFactory* factory_; + const CallHeaders& headers_; + std::shared_ptr session_; + std::string session_id_; + const bool existing_session; + + public: + ServerSessionMiddlewareImpl(ServerSessionMiddlewareFactory* factory, + const CallHeaders& headers) + : factory_(factory), headers_(headers), existing_session(false) {} + + ServerSessionMiddlewareImpl( + ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, + std::shared_ptr session, std::string session_id) + : factory_(factory), + headers_(headers), + session_(std::move(session)), + session_id_(std::move(session_id)), + existing_session(true) {} + + void SendingHeaders(AddCallHeaders* add_call_headers) override { + if (!existing_session && session_) { + add_call_headers->AddHeader( + "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); + } + } + + void CallCompleted(const Status&) override {} + + bool HasSession() const override { return static_cast(session_); } + + std::shared_ptr GetSession() override { + if (!session_) + session_ = factory_->GetNewSession(&session_id_); + return session_; + } + + const CallHeaders& GetCallHeaders() const override { return headers_; } +}; + + std::vector> ServerSessionMiddlewareFactory::ParseCookieString( const std::string_view& s) { const std::string list_sep = "; "; const std::string pair_sep = "="; @@ -68,8 +121,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { return result; } - public: - Status StartCall(const CallInfo&, const CallHeaders& incoming_headers, + Status ServerSessionMiddlewareFactory::StartCall(const CallInfo&, const CallHeaders& incoming_headers, std::shared_ptr* middleware) { std::string session_id; @@ -82,7 +134,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { for (const std::pair& cookie : cookies) { if (cookie.first == kSessionCookieName) { if (cookie.second.empty()) - return Status::Invalid("Empty "s + kSessionCookieName + " cookie value."); + return Status::Invalid("Empty ", kSessionCookieName, " cookie value."); session_id = std::move(cookie.second); } } @@ -91,16 +143,15 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { if (session_id.empty()) { // No cookie was found - *middleware = std::shared_ptr( // PHOXME needs to be properly pimpl w/ public constructor to make_shared (then fix that) - new ServerSessionMiddleware(this, incoming_headers)); + *middleware = std::make_shared(this, incoming_headers); } else { - try { - const std::shared_lock l(session_store_lock_); + const std::shared_lock l(session_store_lock_); + if (!session_store_.count(session_id)) { + return Status::Invalid("Invalid or expired ", kSessionCookieName, " cookie."); + } else { auto session = session_store_.at(session_id); - *middleware = std::shared_ptr( - new ServerSessionMiddleware(this, incoming_headers, session, session_id)); - } catch (std::out_of_range& e) { - return Status::Invalid("Invalid or expired "s + kSessionCookieName + " cookie."); + *middleware = std::make_shared( + this, incoming_headers, std::move(session), session_id); } } @@ -108,7 +159,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { } /// \brief Get a new, empty session option map and its id key. - std::shared_ptr GetNewSession(std::string* session_id) { + std::shared_ptr ServerSessionMiddlewareFactory::GetNewSession(std::string* session_id) { std::string new_id = boost::lexical_cast(uuid_generator_()); *session_id = new_id; auto session = std::make_shared(); @@ -118,50 +169,19 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { return session; } -}; - -ServerSessionMiddleware::ServerSessionMiddleware(ServerSessionMiddlewareFactory* factory, - const CallHeaders& headers) - : factory_(factory), headers_(headers), existing_session(false) {} - -ServerSessionMiddleware::ServerSessionMiddleware( - ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, - std::shared_ptr session, std::string session_id) - : factory_(factory), - headers_(headers), - session_(std::move(session)), - session_id_(std::move(session_id)), - existing_session(true) {} - -void ServerSessionMiddleware::SendingHeaders(AddCallHeaders* add_call_headers) { - if (!existing_session && session_) { - add_call_headers->AddHeader( - "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); - } -} - -void ServerSessionMiddleware::CallCompleted(const Status&) {} - -bool ServerSessionMiddleware::HasSession() const { return static_cast(session_); } - -std::shared_ptr ServerSessionMiddleware::GetSession() { - if (!session_) session_ = factory_->GetNewSession(&session_id_); - return session_; -} -const CallHeaders& ServerSessionMiddleware::GetCallHeaders() const { return headers_; } std::shared_ptr MakeServerSessionMiddlewareFactory() { return std::make_shared(); } -::arrow::Result FlightSqlSession::GetSessionOption( +::arrow::Result> FlightSqlSession::GetSessionOption( const std::string& k) { const std::shared_lock l(map_lock_); - try { + if (map_.count(k)) { return map_.at(k); - } catch (const std::out_of_range& e) { - return ::arrow::Status::KeyError("Session option key '" + k + "' not found."); + } else { + return std::nullopt; } } diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 7cef409eaecbd..1f99a828d0c6b 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include @@ -30,8 +31,6 @@ namespace arrow { namespace flight { namespace sql { -class ServerSessionMiddlewareFactory; - static constexpr char const kSessionCookieName[] = "arrow_flight_session_id"; class FlightSqlSession { @@ -41,7 +40,8 @@ class FlightSqlSession { public: /// \brief Get session option by key - ::arrow::Result GetSessionOption(const std::string&); + ::arrow::Result> + GetSessionOption(const std::string&); /// \brief Set session option by key to given value void SetSessionOption(const std::string&, const SessionOptionValue&); /// \brief Idempotently remove key from this call's Session, if Session & key exist @@ -55,27 +55,15 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware "arrow::flight::sql::ServerSessionMiddleware"; std::string name() const override { return kMiddlewareName; } - void SendingHeaders(AddCallHeaders*) override; - void CallCompleted(const Status&) override; /// \brief Is there an existing session (either existing or new) - bool HasSession() const; + virtual bool HasSession() const; /// \brief Get existing or new call-associated session - std::shared_ptr GetSession(); + virtual std::shared_ptr GetSession(); /// \brief Get request headers, in lieu of a provided or created session. - const CallHeaders& GetCallHeaders() const; - + virtual const CallHeaders& GetCallHeaders() const; protected: - friend class ServerSessionMiddlewareFactory; - ServerSessionMiddlewareFactory* factory_; - const CallHeaders& headers_; - std::shared_ptr session_; - std::string session_id_; - const bool existing_session; - - ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders&); - ServerSessionMiddleware(ServerSessionMiddlewareFactory*, const CallHeaders&, - std::shared_ptr, std::string session_id); + ServerSessionMiddleware() {} }; /// \brief Returns a ServerMiddlewareFactory that handles Session option storage. From 992d9f03d0e34f1c110afeedb7d27aaec9c67bbb Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 10 Nov 2023 12:21:59 -0800 Subject: [PATCH 063/195] [builds] Finish refactor to use map.find() --- .../flight/sql/server_session_middleware.cc | 142 +++++++++--------- cpp/src/arrow/flight/types.cc | 10 +- 2 files changed, 76 insertions(+), 76 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 98ca9d7b24234..351831d26fc67 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -87,89 +87,88 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { const CallHeaders& GetCallHeaders() const override { return headers_; } }; - std::vector> ServerSessionMiddlewareFactory::ParseCookieString( - const std::string_view& s) { - const std::string list_sep = "; "; - const std::string pair_sep = "="; - const size_t pair_sep_len = pair_sep.length(); - - std::vector> result; - - size_t cur = 0; - while (cur < s.length()) { - const size_t end = s.find(list_sep, cur); - size_t len; - if (end == std::string::npos) { - // No (further) list delimiters - len = std::string::npos; - cur = s.length(); - } else { - len = end - cur; - cur = end; - } - const std::string_view tok = s.substr(cur, len); - - const size_t val_pos = tok.find(pair_sep); - if (val_pos == std::string::npos) { - // The cookie header is somewhat malformed; ignore the key and continue parsing - continue; - } - result.emplace_back(tok.substr(0, val_pos), - tok.substr(val_pos + pair_sep_len, std::string::npos)); +std::vector> ServerSessionMiddlewareFactory::ParseCookieString( + const std::string_view& s) { + const std::string list_sep = "; "; + const std::string pair_sep = "="; + const size_t pair_sep_len = pair_sep.length(); + + std::vector> result; + + size_t cur = 0; + while (cur < s.length()) { + const size_t end = s.find(list_sep, cur); + size_t len; + if (end == std::string::npos) { + // No (further) list delimiters + len = std::string::npos; + cur = s.length(); + } else { + len = end - cur; + cur = end; } + const std::string_view tok = s.substr(cur, len); - return result; + const size_t val_pos = tok.find(pair_sep); + if (val_pos == std::string::npos) { + // The cookie header is somewhat malformed; ignore the key and continue parsing + continue; + } + result.emplace_back(tok.substr(0, val_pos), + tok.substr(val_pos + pair_sep_len, std::string::npos)); } - Status ServerSessionMiddlewareFactory::StartCall(const CallInfo&, const CallHeaders& incoming_headers, - std::shared_ptr* middleware) { - std::string session_id; - - const std::pair& - headers_it_pr = incoming_headers.equal_range("cookie"); - for (auto itr = headers_it_pr.first; itr != headers_it_pr.second; ++itr) { - const std::string_view& cookie_header = itr->second; - const std::vector> cookies = - ParseCookieString(cookie_header); - for (const std::pair& cookie : cookies) { - if (cookie.first == kSessionCookieName) { - if (cookie.second.empty()) - return Status::Invalid("Empty ", kSessionCookieName, " cookie value."); - session_id = std::move(cookie.second); - } + return result; +} + +Status ServerSessionMiddlewareFactory::StartCall(const CallInfo&, const CallHeaders& incoming_headers, + std::shared_ptr* middleware) { + std::string session_id; + + const std::pair& + headers_it_pr = incoming_headers.equal_range("cookie"); + for (auto itr = headers_it_pr.first; itr != headers_it_pr.second; ++itr) { + const std::string_view& cookie_header = itr->second; + const std::vector> cookies = + ParseCookieString(cookie_header); + for (const std::pair& cookie : cookies) { + if (cookie.first == kSessionCookieName) { + if (cookie.second.empty()) + return Status::Invalid("Empty ", kSessionCookieName, " cookie value."); + session_id = std::move(cookie.second); } - if (!session_id.empty()) break; } + if (!session_id.empty()) break; + } - if (session_id.empty()) { - // No cookie was found - *middleware = std::make_shared(this, incoming_headers); + if (session_id.empty()) { + // No cookie was found + *middleware = std::make_shared(this, incoming_headers); + } else { + const std::shared_lock l(session_store_lock_); + if (auto it = session_store_.find(session_id); it == session_store_.end()) { + return Status::Invalid("Invalid or expired ", kSessionCookieName, " cookie."); } else { - const std::shared_lock l(session_store_lock_); - if (!session_store_.count(session_id)) { - return Status::Invalid("Invalid or expired ", kSessionCookieName, " cookie."); - } else { - auto session = session_store_.at(session_id); - *middleware = std::make_shared( - this, incoming_headers, std::move(session), session_id); - } + auto session = it->second; + *middleware = std::make_shared( + this, incoming_headers, std::move(session), session_id); } - - return Status::OK(); } - /// \brief Get a new, empty session option map and its id key. - std::shared_ptr ServerSessionMiddlewareFactory::GetNewSession(std::string* session_id) { - std::string new_id = boost::lexical_cast(uuid_generator_()); - *session_id = new_id; - auto session = std::make_shared(); + return Status::OK(); +} - const std::unique_lock l(session_store_lock_); - session_store_[new_id] = session; +/// \brief Get a new, empty session option map and its id key. +std::shared_ptr ServerSessionMiddlewareFactory::GetNewSession(std::string* session_id) { + std::string new_id = boost::lexical_cast(uuid_generator_()); + *session_id = new_id; + auto session = std::make_shared(); - return session; - } + const std::unique_lock l(session_store_lock_); + session_store_[new_id] = session; + return session; +} std::shared_ptr MakeServerSessionMiddlewareFactory() { return std::make_shared(); @@ -178,8 +177,9 @@ std::shared_ptr MakeServerSessionMiddlewareFactory() { ::arrow::Result> FlightSqlSession::GetSessionOption( const std::string& k) { const std::shared_lock l(map_lock_); - if (map_.count(k)) { - return map_.at(k); + auto it = map_.find(k); + if (it != map_.end()) { + return it->second; } else { return std::nullopt; } diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 56d92394cc17c..b4e4e2da66f4c 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -524,16 +524,16 @@ static bool CompareSessionOptionMaps(const std::mapsecond; if (v.index() != b_v.index()) { return false; } - if (v != b_v) { + if (v != b_v) { return false; } - } catch (const std::out_of_range& e) { - return false; } } return true; From 75d0c4e9e1cbf6f4e974d71dabc955162ea526df Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 10 Nov 2023 12:40:19 -0800 Subject: [PATCH 064/195] Remove extraneous using namespace --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 351831d26fc67..1c1cd7b6ab5f7 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -21,8 +21,6 @@ #include #include -using namespace std::string_literals; - namespace arrow { namespace flight { namespace sql { From 13afc00701f29932fd6cfa5e43b5f0a3d15bad09 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 10 Nov 2023 12:57:20 -0800 Subject: [PATCH 065/195] [builds] Factor out session ID generation & remove Boost --- .../flight/sql/server_session_middleware.cc | 24 ++++++++++--------- .../flight/sql/server_session_middleware.h | 8 ++++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 1c1cd7b6ab5f7..7a643403cb371 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -16,10 +16,6 @@ // under the License. #include "arrow/flight/sql/server_session_middleware.h" -#include -#include -#include -#include namespace arrow { namespace flight { @@ -30,12 +26,14 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { protected: std::map> session_store_; std::shared_mutex session_store_lock_; - boost::uuids::random_generator uuid_generator_; + std::function id_generator_; std::vector> ParseCookieString( const std::string_view& s); public: + ServerSessionMiddlewareFactory(std::function id_gen) + : id_generator_(id_gen) {} Status StartCall(const CallInfo&, const CallHeaders& incoming_headers, std::shared_ptr* middleware); @@ -85,7 +83,8 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { const CallHeaders& GetCallHeaders() const override { return headers_; } }; -std::vector> ServerSessionMiddlewareFactory::ParseCookieString( +std::vector> +ServerSessionMiddlewareFactory::ParseCookieString( const std::string_view& s) { const std::string list_sep = "; "; const std::string pair_sep = "="; @@ -119,7 +118,8 @@ std::vector> ServerSessionMiddlewareFactory: return result; } -Status ServerSessionMiddlewareFactory::StartCall(const CallInfo&, const CallHeaders& incoming_headers, +Status ServerSessionMiddlewareFactory::StartCall( + const CallInfo&, const CallHeaders& incoming_headers, std::shared_ptr* middleware) { std::string session_id; @@ -157,8 +157,9 @@ Status ServerSessionMiddlewareFactory::StartCall(const CallInfo&, const CallHead } /// \brief Get a new, empty session option map and its id key. -std::shared_ptr ServerSessionMiddlewareFactory::GetNewSession(std::string* session_id) { - std::string new_id = boost::lexical_cast(uuid_generator_()); +std::shared_ptr +ServerSessionMiddlewareFactory::GetNewSession(std::string* session_id) { + std::string new_id = id_generator_(); *session_id = new_id; auto session = std::make_shared(); @@ -168,8 +169,9 @@ std::shared_ptr ServerSessionMiddlewareFactory::GetNewSession( return session; } -std::shared_ptr MakeServerSessionMiddlewareFactory() { - return std::make_shared(); +std::shared_ptr +MakeServerSessionMiddlewareFactory(std::function id_gen) { + return std::make_shared(std::move(id_gen)); } ::arrow::Result> FlightSqlSession::GetSessionOption( diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 1f99a828d0c6b..c5e5e0aff2e40 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -20,6 +20,7 @@ #pragma once +#include #include #include #include @@ -43,9 +44,9 @@ class FlightSqlSession { ::arrow::Result> GetSessionOption(const std::string&); /// \brief Set session option by key to given value - void SetSessionOption(const std::string&, const SessionOptionValue&); + void SetSessionOption(const std::string& key, const SessionOptionValue& v); /// \brief Idempotently remove key from this call's Session, if Session & key exist - void EraseSessionOption(const std::string&); + void EraseSessionOption(const std::string& key); }; /// \brief A middleware to handle Session option persistence and related *Cookie headers. @@ -67,8 +68,9 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware }; /// \brief Returns a ServerMiddlewareFactory that handles Session option storage. +/// \param[in] id_gen A generator function for unique session id strings. ARROW_FLIGHT_SQL_EXPORT std::shared_ptr -MakeServerSessionMiddlewareFactory(); +MakeServerSessionMiddlewareFactory(std::function id_gen); } // namespace sql } // namespace flight From b56f21da8769a19fb6562c133b62f44ed3a6e6e1 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 10 Nov 2023 13:09:36 -0800 Subject: [PATCH 066/195] [builds] make GetNewSession return std::pair --- .../flight/sql/server_session_middleware.cc | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 7a643403cb371..2a555d5fed3f3 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -38,11 +38,12 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { std::shared_ptr* middleware); /// \brief Get a new, empty session option map and its id key. - std::shared_ptr GetNewSession(std::string* session_id); + std::pair> GetNewSession(); }; class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { protected: + std::shared_mutex lock_; ServerSessionMiddlewareFactory* factory_; const CallHeaders& headers_; std::shared_ptr session_; @@ -75,8 +76,12 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { bool HasSession() const override { return static_cast(session_); } std::shared_ptr GetSession() override { - if (!session_) - session_ = factory_->GetNewSession(&session_id_); + const std::shared_lock l(lock_); + if (!session_) { + auto [id, s] = factory_->GetNewSession(); + session_ = std::move(s); + session_id_ = std::move(id); + } return session_; } @@ -157,16 +162,15 @@ Status ServerSessionMiddlewareFactory::StartCall( } /// \brief Get a new, empty session option map and its id key. -std::shared_ptr -ServerSessionMiddlewareFactory::GetNewSession(std::string* session_id) { +std::pair> +ServerSessionMiddlewareFactory::GetNewSession() { std::string new_id = id_generator_(); - *session_id = new_id; auto session = std::make_shared(); const std::unique_lock l(session_store_lock_); session_store_[new_id] = session; - return session; + return {new_id, session}; } std::shared_ptr From 20acab675e9f101c2dc6aae353e0ce0003b14d08 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 10 Nov 2023 13:14:18 -0800 Subject: [PATCH 067/195] [builds] Fix argument forwarding for FlightSqlSession::SetSessionOption --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 4 ++-- cpp/src/arrow/flight/sql/server_session_middleware.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 2a555d5fed3f3..4b38c2e53d792 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -190,9 +190,9 @@ ::arrow::Result> FlightSqlSession::GetSessionO } void FlightSqlSession::SetSessionOption(const std::string& k, - const SessionOptionValue& v) { + const SessionOptionValue v) { const std::unique_lock l(map_lock_); - map_[k] = v; + map_[k] = std::move(v); } void FlightSqlSession::EraseSessionOption(const std::string& k) { diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index c5e5e0aff2e40..012d65d3d7175 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -44,7 +44,7 @@ class FlightSqlSession { ::arrow::Result> GetSessionOption(const std::string&); /// \brief Set session option by key to given value - void SetSessionOption(const std::string& key, const SessionOptionValue& v); + void SetSessionOption(const std::string& key, const SessionOptionValue v); /// \brief Idempotently remove key from this call's Session, if Session & key exist void EraseSessionOption(const std::string& key); }; From 76c21f50f8ead99342db5b2f39200ae2e16fb7d2 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 10 Nov 2023 13:26:49 -0800 Subject: [PATCH 068/195] [builds] Docs fixup --- cpp/src/arrow/flight/types.h | 9 +++++++++ format/Flight.proto | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 233132e9dbda6..c22a13f6a618f 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -771,11 +771,20 @@ using SessionOptionValue = std::variant Date: Tue, 14 Nov 2023 18:29:02 -0800 Subject: [PATCH 069/195] [builds] move SetSessionOptionsResult status to estensible nested msg --- .../arrow/flight/serialization_internal.cc | 12 +++++++----- cpp/src/arrow/flight/types.cc | 9 +++++++-- cpp/src/arrow/flight/types.h | 19 ++++++++++++++++++- format/Flight.proto | 6 +++++- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 326a4b478958c..4548e824ef53f 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -477,17 +477,19 @@ Status ToProto(const SetSessionOptionsRequest& request, Status FromProto(const pb::SetSessionOptionsResult& pb_result, SetSessionOptionsResult* result) { - for (const auto& [k, pb_v] : pb_result.statuses()) { - result->statuses.insert({k, static_cast(pb_v)}); + for (const auto& [k, pb_v] : pb_result.results()) { + result->results.insert({k, {static_cast(pb_v.status())}}); } return Status::OK(); } Status ToProto(const SetSessionOptionsResult& result, pb::SetSessionOptionsResult* pb_result) { - auto* pb_statuses = pb_result->mutable_statuses(); - for (const auto& [k, v] : result.statuses) { - (*pb_statuses)[k] = static_cast(v); + auto* pb_statuses = pb_result->mutable_results(); + for (const auto& [k, v] : result.results) { + pb::SetSessionOptionsResult::Result r; + r.set_status(static_cast(v.status)); + (*pb_statuses)[k] = std::move(r); } return Status::OK(); } diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index b4e4e2da66f4c..c42e3785cca76 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -501,6 +501,11 @@ std::ostream& operator<<(std::ostream& os, const SessionOptionValue& v) { return os; } +std::ostream& operator<<(std::ostream& os, const SetSessionOptionsResult::Result& r) { + os << '{' << r.status << '}'; + return os; +} + template std::ostream& operator<<(std::ostream& os, std::map m) { os << '{'; @@ -588,13 +593,13 @@ arrow::Result SetSessionOptionsRequest::Deserialize( std::string SetSessionOptionsResult::ToString() const { std::stringstream ss; - ss << " map_; std::shared_mutex map_lock_; From 8ea8911f4389bad7f89ec8ca648743e61d2e6071 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 15 Nov 2023 12:52:04 -0800 Subject: [PATCH 072/195] [builds] PR feedback fixups --- cpp/src/arrow/flight/client.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/client.h b/cpp/src/arrow/flight/client.h index 68fa0ff67d040..eb84699e5db55 100644 --- a/cpp/src/arrow/flight/client.h +++ b/cpp/src/arrow/flight/client.h @@ -383,21 +383,21 @@ class ARROW_FLIGHT_EXPORT FlightClient { return DoExchange({}, descriptor); } - /// \\brief Set server session option(s) by key/value. Sessions are generally + /// \brief Set server session option(s) by key/value. Sessions are generally /// persisted via HTTP cookies. /// \param[in] options Per-RPC options /// \param[in] request The server session options to set ::arrow::Result SetSessionOptions( const FlightCallOptions& options, const SetSessionOptionsRequest& request); - /// \\brief Get the current server session options. The session is generally + /// \brief Get the current server session options. The session is generally /// accessed via an HTTP cookie. /// \param[in] options Per-RPC options /// \param[in] request The (empty) GetSessionOptions request object. ::arrow::Result GetSessionOptions( const FlightCallOptions& options, const GetSessionOptionsRequest& request); - /// \\brief Close/invalidate the current server session. The session is generally + /// \brief Close/invalidate the current server session. The session is generally /// accessed via an HTTP cookie. /// \param[in] options Per-RPC options /// \param[in] request The (empty) CloseSession request object. From dfccca7f76e7ac73e8c66166ab51b52ae29fdaae Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 15 Nov 2023 13:02:20 -0800 Subject: [PATCH 073/195] [builds] Add virtual default destructor to ServerSessionMiddleware --- cpp/src/arrow/flight/sql/server_session_middleware.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index acb019634fb0d..6bee62fc188b8 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -62,8 +62,8 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware virtual std::shared_ptr GetSession(); /// \brief Get request headers, in lieu of a provided or created session. virtual const CallHeaders& GetCallHeaders() const; - protected: - ServerSessionMiddleware() {} + + virtual ~ServerSessionMiddleware() = default; }; /// \brief Returns a ServerMiddlewareFactory that handles Session option storage. From 41c04be7c65ea8de2fa32f8d21c4dfac73df36de Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 15 Nov 2023 13:23:28 -0800 Subject: [PATCH 074/195] [builds] Fix CI linter issues. --- .../flight/sql/server_session_middleware.cc | 28 +++++++++---------- cpp/src/arrow/flight/types.cc | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 25c567806208a..a69afbafdf02b 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -43,7 +43,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { protected: - std::shared_mutex lock_; + std::shared_mutex lock_; ServerSessionMiddlewareFactory* factory_; const CallHeaders& headers_; std::shared_ptr session_; @@ -52,12 +52,13 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { public: ServerSessionMiddlewareImpl(ServerSessionMiddlewareFactory* factory, - const CallHeaders& headers) + const CallHeaders& headers) : factory_(factory), headers_(headers), existing_session(false) {} - ServerSessionMiddlewareImpl( - ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, - std::shared_ptr session, std::string session_id) + ServerSessionMiddlewareImpl(ServerSessionMiddlewareFactory* factory, + const CallHeaders& headers, + std::shared_ptr session, + std::string session_id) : factory_(factory), headers_(headers), session_(std::move(session)), @@ -66,8 +67,8 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { void SendingHeaders(AddCallHeaders* add_call_headers) override { if (!existing_session && session_) { - add_call_headers->AddHeader( - "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); + add_call_headers->AddHeader( + "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); } } @@ -89,8 +90,7 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { }; std::vector> -ServerSessionMiddlewareFactory::ParseCookieString( - const std::string_view& s) { +ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { const std::string list_sep = "; "; const std::string pair_sep = "="; const size_t pair_sep_len = pair_sep.length(); @@ -124,8 +124,8 @@ ServerSessionMiddlewareFactory::ParseCookieString( } Status ServerSessionMiddlewareFactory::StartCall( - const CallInfo&, const CallHeaders& incoming_headers, - std::shared_ptr* middleware) { + const CallInfo&, const CallHeaders& incoming_headers, + std::shared_ptr* middleware) { std::string session_id; const std::pair& @@ -154,7 +154,7 @@ Status ServerSessionMiddlewareFactory::StartCall( } else { auto session = it->second; *middleware = std::make_shared( - this, incoming_headers, std::move(session), session_id); + this, incoming_headers, std::move(session), session_id); } } @@ -173,8 +173,8 @@ ServerSessionMiddlewareFactory::GetNewSession() { return {new_id, session}; } -std::shared_ptr -MakeServerSessionMiddlewareFactory(std::function id_gen) { +std::shared_ptr MakeServerSessionMiddlewareFactory( + std::function id_gen) { return std::make_shared(std::move(id_gen)); } diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index c42e3785cca76..b9460a31da323 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -536,7 +536,7 @@ static bool CompareSessionOptionMaps(const std::map Date: Wed, 15 Nov 2023 13:46:18 -0800 Subject: [PATCH 075/195] [builds] Fix abstract subclass ServerSessionMiddleware. --- cpp/src/arrow/flight/sql/server_session_middleware.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 6bee62fc188b8..ca84a08923bf3 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -57,13 +57,11 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware std::string name() const override { return kMiddlewareName; } /// \brief Is there an existing session (either existing or new) - virtual bool HasSession() const; + virtual bool HasSession() const = 0; /// \brief Get existing or new call-associated session - virtual std::shared_ptr GetSession(); + virtual std::shared_ptr GetSession() = 0; /// \brief Get request headers, in lieu of a provided or created session. - virtual const CallHeaders& GetCallHeaders() const; - - virtual ~ServerSessionMiddleware() = default; + virtual const CallHeaders& GetCallHeaders() const = 0; }; /// \brief Returns a ServerMiddlewareFactory that handles Session option storage. From 4117a4f4b5469faca5b789160dd1140c419a25b2 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 15 Nov 2023 14:45:41 -0800 Subject: [PATCH 076/195] [builds] WHOOPS: Fix tangled/redundant Session ActionTypes --- cpp/src/arrow/flight/sql/server.cc | 6 +++--- cpp/src/arrow/flight/sql/server.h | 15 --------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server.cc b/cpp/src/arrow/flight/sql/server.cc index f0842381e7fef..a5cb842de8f49 100644 --- a/cpp/src/arrow/flight/sql/server.cc +++ b/cpp/src/arrow/flight/sql/server.cc @@ -782,11 +782,11 @@ Status FlightSqlServerBase::ListActions(const ServerCallContext& context, FlightSqlServerBase::kCreatePreparedStatementActionType, FlightSqlServerBase::kCreatePreparedSubstraitPlanActionType, FlightSqlServerBase::kClosePreparedStatementActionType, - FlightSqlServerBase::kCloseSessionActionType, FlightSqlServerBase::kEndSavepointActionType, FlightSqlServerBase::kEndTransactionActionType, - FlightSqlServerBase::kSetSessionOptionsActionType, - FlightSqlServerBase::kGetSessionOptionsActionType}; + ActionType::kSetSessionOptions, + ActionType::kGetSessionOptions, + ActionType::kCloseSession}; return Status::OK(); } diff --git a/cpp/src/arrow/flight/sql/server.h b/cpp/src/arrow/flight/sql/server.h index 9af9ce803c576..df46004474a39 100644 --- a/cpp/src/arrow/flight/sql/server.h +++ b/cpp/src/arrow/flight/sql/server.h @@ -701,11 +701,6 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlServerBase : public FlightServerBase { "Closes a reusable prepared statement resource on the server.\n" "Request Message: ActionClosePreparedStatementRequest\n" "Response Message: N/A"}; - const ActionType kCloseSessionActionType = - ActionType{"CloseSession", - "Explicitly close an open session.\n" - "Request Message: CloseSessionRequest\n" - "Response Message: ActionCloseSessionResult"}; const ActionType kEndSavepointActionType = ActionType{"EndSavepoint", "End a savepoint.\n" @@ -716,16 +711,6 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlServerBase : public FlightServerBase { "End a savepoint.\n" "Request Message: ActionEndTransactionRequest\n" "Response Message: N/A"}; - const ActionType kSetSessionOptionsActionType = - ActionType{"SetSessionOptions", - "Set a series of session options.\n" - "Request Message: SetSessionOptionsRequest\n" - "Response Message: SetSessionOptionsResult"}; - const ActionType kGetSessionOptionsActionType = - ActionType{"GetSessionOption", - "Get a series of session options.\n" - "Request Message: ActionGetSessionOptionRequest\n" - "Response Message: ActionGetSessionOptionResult"}; Status ListActions(const ServerCallContext& context, std::vector* actions) final; From c33d4cb5c3821c4ff9689e2290450bf7e78f0d72 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 16 Nov 2023 12:35:58 -0800 Subject: [PATCH 077/195] [builds] CI fixups --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index a69afbafdf02b..e788a83661c7e 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -15,6 +15,8 @@ // specific language governing permissions and limitations // under the License. +#include + #include "arrow/flight/sql/server_session_middleware.h" namespace arrow { @@ -32,7 +34,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { const std::string_view& s); public: - ServerSessionMiddlewareFactory(std::function id_gen) + explicit ServerSessionMiddlewareFactory(std::function id_gen) : id_generator_(id_gen) {} Status StartCall(const CallInfo&, const CallHeaders& incoming_headers, std::shared_ptr* middleware); From 5cc856b0c79c18bf63a9483aa8980d3c787150a6 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 16 Nov 2023 13:51:51 -0800 Subject: [PATCH 078/195] [builds] Remove redundant branch --- cpp/src/arrow/flight/types.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index b9460a31da323..2a95057cb3a1a 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -526,9 +526,6 @@ static bool CompareSessionOptionMaps(const std::map Date: Fri, 17 Nov 2023 13:38:20 -0800 Subject: [PATCH 079/195] [builds] Fix reader/writer locks --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index e788a83661c7e..3edc979615135 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -79,7 +79,7 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { bool HasSession() const override { return static_cast(session_); } std::shared_ptr GetSession() override { - const std::shared_lock l(lock_); + const std::lock_guard l(lock_); if (!session_) { auto [id, s] = factory_->GetNewSession(); session_ = std::move(s); @@ -169,7 +169,7 @@ ServerSessionMiddlewareFactory::GetNewSession() { std::string new_id = id_generator_(); auto session = std::make_shared(); - const std::unique_lock l(session_store_lock_); + const std::lock_guard l(session_store_lock_); session_store_[new_id] = session; return {new_id, session}; @@ -193,12 +193,12 @@ std::optional FlightSqlSession::GetSessionOption( void FlightSqlSession::SetSessionOption(const std::string& k, const SessionOptionValue v) { - const std::unique_lock l(map_lock_); + const std::lock_guard l(map_lock_); map_[k] = std::move(v); } void FlightSqlSession::EraseSessionOption(const std::string& k) { - const std::unique_lock l(map_lock_); + const std::lock_guard l(map_lock_); map_.erase(k); } From baef34a028e68c2d23d78c9645432890bee983c6 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 17 Nov 2023 13:40:19 -0800 Subject: [PATCH 080/195] [builds] Remove extraneous include --- cpp/src/arrow/flight/sql/protocol_internal.h | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/protocol_internal.h b/cpp/src/arrow/flight/sql/protocol_internal.h index dfe32abf0245d..ce50ad2f61b1e 100644 --- a/cpp/src/arrow/flight/sql/protocol_internal.h +++ b/cpp/src/arrow/flight/sql/protocol_internal.h @@ -23,5 +23,4 @@ #include "arrow/flight/sql/visibility.h" -#include "arrow/flight/Flight.pb.h" #include "arrow/flight/sql/FlightSql.pb.h" // IWYU pragma: export From f349a34ab93b96900e96ae7129f92722c614aecf Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 17 Nov 2023 14:09:53 -0800 Subject: [PATCH 081/195] Apply @kou suggestions from code review Co-authored-by: Sutou Kouhei --- .../arrow/flight/sql/server_session_middleware.cc | 4 ++-- .../arrow/flight/sql/server_session_middleware.h | 6 +++--- cpp/src/arrow/flight/types.cc | 15 ++++++--------- cpp/src/arrow/flight/types.h | 7 ++----- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 3edc979615135..00c8beae2e671 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -95,7 +95,7 @@ std::vector> ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { const std::string list_sep = "; "; const std::string pair_sep = "="; - const size_t pair_sep_len = pair_sep.length(); + const auto pair_sep_len = pair_sep.length(); std::vector> result; @@ -166,7 +166,7 @@ Status ServerSessionMiddlewareFactory::StartCall( /// \brief Get a new, empty session option map and its id key. std::pair> ServerSessionMiddlewareFactory::GetNewSession() { - std::string new_id = id_generator_(); + auto new_id = id_generator_(); auto session = std::make_shared(); const std::lock_guard l(session_store_lock_); diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index ca84a08923bf3..c51844e849f87 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -48,7 +48,7 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlSession { void EraseSessionOption(const std::string& key); }; -/// \brief A middleware to handle Session option persistence and related *Cookie headers. +/// \brief A middleware to handle session option persistence and related cookie headers. class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware { public: static constexpr char const kMiddlewareName[] = @@ -64,8 +64,8 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware virtual const CallHeaders& GetCallHeaders() const = 0; }; -/// \brief Returns a ServerMiddlewareFactory that handles Session option storage. -/// \param[in] id_gen A generator function for unique session id strings. +/// \brief Returns a ServerMiddlewareFactory that handles session option storage. +/// \param[in] id_gen A generator function for unique session ID strings. ARROW_FLIGHT_SQL_EXPORT std::shared_ptr MakeServerSessionMiddlewareFactory(std::function id_gen); diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 2a95057cb3a1a..349f37c174483 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -484,11 +484,11 @@ std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& r) { } // Helpers for stringifying maps containing various types -std::ostream& operator<<(std::ostream& os, std::vector v) { +std::ostream& operator<<(std::ostream& os, std::vector values) { os << '['; std::string sep = ""; - for (const auto& x : v) { - os << sep << '"' << x << '"'; + for (const auto& v : values) { + os << sep << '"' << v << '"'; sep = ", "; } os << ']'; @@ -748,16 +748,13 @@ arrow::Result CloseSessionRequest::Deserialize( std::string CloseSessionResult::ToString() const { std::stringstream ss; - ss << " session_options; @@ -827,10 +827,7 @@ struct ARROW_FLIGHT_EXPORT SetSessionOptionsResult { SetSessionOptionStatus status; bool Equals(const Result& other) const { - if (status != other.status) { - return false; - } - return true; + return status == other.status; } friend bool operator==(const Result& left, const Result& right) { return left.Equals(right); From a622032cd58df1e3c320f492f977b3f463cce0ae Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 17 Nov 2023 14:12:36 -0800 Subject: [PATCH 082/195] [builds] More @kou feedback integrated --- .../flight/sql/server_session_middleware.cc | 32 +++++++++---------- .../flight/sql/server_session_middleware.h | 12 +++---- cpp/src/arrow/flight/types.cc | 10 +++--- cpp/src/arrow/flight/types.h | 8 ++--- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 00c8beae2e671..276ccb0ad5ffa 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -40,22 +40,22 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { std::shared_ptr* middleware); /// \brief Get a new, empty session option map and its id key. - std::pair> GetNewSession(); + std::pair> CreateNewSession(); }; class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { protected: - std::shared_mutex lock_; + std::shared_mutex mutex_; ServerSessionMiddlewareFactory* factory_; const CallHeaders& headers_; std::shared_ptr session_; std::string session_id_; - const bool existing_session; + const bool existing_session_; public: ServerSessionMiddlewareImpl(ServerSessionMiddlewareFactory* factory, const CallHeaders& headers) - : factory_(factory), headers_(headers), existing_session(false) {} + : factory_(factory), headers_(headers), existing_session_(false) {} ServerSessionMiddlewareImpl(ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, @@ -65,10 +65,10 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { headers_(headers), session_(std::move(session)), session_id_(std::move(session_id)), - existing_session(true) {} + existing_session_(true) {} void SendingHeaders(AddCallHeaders* add_call_headers) override { - if (!existing_session && session_) { + if (!existing_session_ && session_) { add_call_headers->AddHeader( "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); } @@ -79,9 +79,9 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { bool HasSession() const override { return static_cast(session_); } std::shared_ptr GetSession() override { - const std::lock_guard l(lock_); + const std::lock_guard l(mutex_); if (!session_) { - auto [id, s] = factory_->GetNewSession(); + auto [id, s] = factory_->CreateNewSession(); session_ = std::move(s); session_id_ = std::move(id); } @@ -165,7 +165,7 @@ Status ServerSessionMiddlewareFactory::StartCall( /// \brief Get a new, empty session option map and its id key. std::pair> -ServerSessionMiddlewareFactory::GetNewSession() { +ServerSessionMiddlewareFactory::CreateNewSession() { auto new_id = id_generator_(); auto session = std::make_shared(); @@ -181,9 +181,9 @@ std::shared_ptr MakeServerSessionMiddlewareFactory( } std::optional FlightSqlSession::GetSessionOption( - const std::string& k) { + const std::string& name) { const std::shared_lock l(map_lock_); - auto it = map_.find(k); + auto it = map_.find(name); if (it != map_.end()) { return it->second; } else { @@ -191,15 +191,15 @@ std::optional FlightSqlSession::GetSessionOption( } } -void FlightSqlSession::SetSessionOption(const std::string& k, - const SessionOptionValue v) { +void FlightSqlSession::SetSessionOption(const std::string& name, + const SessionOptionValue value) { const std::lock_guard l(map_lock_); - map_[k] = std::move(v); + map_[name] = std::move(value); } -void FlightSqlSession::EraseSessionOption(const std::string& k) { +void FlightSqlSession::EraseSessionOption(const std::string& name) { const std::lock_guard l(map_lock_); - map_.erase(k); + map_.erase(name); } } // namespace sql diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index c51844e849f87..5a2358658ab47 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -40,12 +40,12 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlSession { std::shared_mutex map_lock_; public: - /// \brief Get session option by key - std::optional GetSessionOption(const std::string&); - /// \brief Set session option by key to given value - void SetSessionOption(const std::string& key, const SessionOptionValue v); - /// \brief Idempotently remove key from this call's Session, if Session & key exist - void EraseSessionOption(const std::string& key); + /// \brief Get session option by name + std::optional GetSessionOption(const std::string& name); + /// \brief Set session option by name to given value + void SetSessionOption(const std::string& name, const SessionOptionValue value); + /// \brief Idempotently remove key from this call's Session, if Session & name exist + void EraseSessionOption(const std::string& name); }; /// \brief A middleware to handle session option persistence and related cookie headers. diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 349f37c174483..f324a71e8db95 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -473,13 +473,13 @@ arrow::Result CancelFlightInfoRequest::Deserialize( return out; } -std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& r) { - os << SetSessionOptionStatusNames[static_cast(r)]; +std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& status) { + os << SetSessionOptionStatusNames[static_cast(status)]; return os; } -std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& r) { - os << CloseSessionStatusNames[static_cast(r)]; +std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& status) { + os << CloseSessionStatusNames[static_cast(status)]; return os; } @@ -511,7 +511,7 @@ std::ostream& operator<<(std::ostream& os, std::map m) { os << '{'; std::string sep = ""; for (const auto& [k, v] : m) { - os << sep << '[' << k << "]: '" << v; + os << sep << '[' << k << "]: '" << v << '\''; sep = ", "; } os << '}'; diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 9a0af35212a64..82de92082d4a5 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -781,20 +781,20 @@ enum class SetSessionOptionStatus : int8_t { /// \brief The given session option name was an alias for another option name. kOkMapped, /// \brief The given session option name is invalid. - kInvalidKey, + kInvalidName, /// \brief The session option value is invalid. kInvalidValue, /// \brief The session option cannot be set. kError }; -std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& r); +std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& status); /// \brief The result of closing a session. enum class CloseSessionStatus : int8_t { kUnspecified, kClosed, kClosing, kNotClosable }; -std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& r); +std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& status); static const char* const SetSessionOptionStatusNames[] = { - "Unspecified", "Ok", "OkMapped", "InvalidKey", "InvalidValue", "Error"}; + "Unspecified", "Ok", "OkMapped", "InvalidName", "InvalidValue", "Error"}; static const char* const CloseSessionStatusNames[] = {"Unspecified", "Closed", "Closing", "NotClosable"}; From 54175aa8ca2ccc2db9c354970037cecb9da90833 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 20 Nov 2023 15:27:17 -0800 Subject: [PATCH 083/195] [builds] Fix docs --- .../flight/sql/server_session_middleware.h | 2 +- cpp/src/arrow/flight/types.h | 20 ++++++++++++++++++- format/Flight.proto | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 5a2358658ab47..c74e1c81bae38 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -65,7 +65,7 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware }; /// \brief Returns a ServerMiddlewareFactory that handles session option storage. -/// \param[in] id_gen A generator function for unique session ID strings. +/// \param[in] id_gen A thread-safe, collision-free generator for session id strings. ARROW_FLIGHT_SQL_EXPORT std::shared_ptr MakeServerSessionMiddlewareFactory(std::function id_gen); diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 82de92082d4a5..61290168353a9 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -790,7 +790,25 @@ enum class SetSessionOptionStatus : int8_t { std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& status); /// \brief The result of closing a session. -enum class CloseSessionStatus : int8_t { kUnspecified, kClosed, kClosing, kNotClosable }; +enum class CloseSessionStatus : int8_t { + // \brief The session close status is unknown. + // + // Servers should avoid using this value (send a NOT_FOUND error if the requested + // session is not known). Clients can retry the request. + kUnspecified, + // \brief The session close request is complete. + // + // Subsequent requests with the same session produce a NOT_FOUND error. + kClosed, + // \brief The session close request is in progress. + // + // The client may retry the request. + kClosing, + // \brief The session is not closeable. + // + // The client should not retry the request. + kNotClosable +}; std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& status); static const char* const SetSessionOptionStatusNames[] = { diff --git a/format/Flight.proto b/format/Flight.proto index d4663feaa4178..dab0ffaa30658 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -614,7 +614,7 @@ message CloseSessionRequest { message CloseSessionResult { enum Status { // The session close status is unknown. Servers should avoid using - // this value (send a NOT_FOUND error if the requested query is + // this value (send a NOT_FOUND error if the requested session is // not known). Clients can retry the request. CLOSE_RESULT_UNSPECIFIED = 0; // The session close request is complete. Subsequent requests with From 722db0f8d849199621466b7ffbe4d95e52395a47 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 20 Nov 2023 16:01:09 -0800 Subject: [PATCH 084/195] [builds] PR feedback --- cpp/src/arrow/flight/types.cc | 37 ++++++++++++++++++++++++++++------- cpp/src/arrow/flight/types.h | 7 ++----- 2 files changed, 32 insertions(+), 12 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index f324a71e8db95..f5fb23c54d7de 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -17,9 +17,11 @@ #include "arrow/flight/types.h" +#include #include #include #include +#include #include #include "arrow/buffer.h" @@ -473,22 +475,35 @@ arrow::Result CancelFlightInfoRequest::Deserialize( return out; } +static const char* const SetSessionOptionStatusNames[] = { + "Unspecified", "Ok", "OkMapped", "InvalidName", "InvalidValue", "Error"}; +static const char* const CloseSessionStatusNames[] = {"Unspecified", "Closed", "Closing", + "NotClosable"}; + +// Helpers for stringifying maps containing various types +std::string ToString(const SetSessionOptionStatus& status) { + return SetSessionOptionStatusNames[static_cast(status)]; +} + std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& status) { - os << SetSessionOptionStatusNames[static_cast(status)]; + os << ToString(status); return os; } +std::string ToString(const CloseSessionStatus& status) { + return CloseSessionStatusNames[static_cast(status)]; +} + std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& status) { - os << CloseSessionStatusNames[static_cast(status)]; + os << ToString(status); return os; } -// Helpers for stringifying maps containing various types std::ostream& operator<<(std::ostream& os, std::vector values) { os << '['; std::string sep = ""; for (const auto& v : values) { - os << sep << '"' << v << '"'; + os << sep << std::quoted(v); sep = ", "; } os << ']'; @@ -510,9 +525,17 @@ template std::ostream& operator<<(std::ostream& os, std::map m) { os << '{'; std::string sep = ""; - for (const auto& [k, v] : m) { - os << sep << '[' << k << "]: '" << v << '\''; - sep = ", "; + if constexpr(std::is_convertible_v) { + // std::string, char*, std::string_view + for (const auto& [k, v] : m) { + os << sep << '[' << k << "]: " << std::quoted(v) << '"'; + sep = ", "; + } + } else { + for (const auto& [k, v] : m) { + os << sep << '[' << k << "]: " << v; + sep = ", "; + } } os << '}'; diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 61290168353a9..73f32d7e789c3 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -787,6 +787,7 @@ enum class SetSessionOptionStatus : int8_t { /// \brief The session option cannot be set. kError }; +std::string ToString(const SetSessionOptionStatus& status); std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& status); /// \brief The result of closing a session. @@ -809,13 +810,9 @@ enum class CloseSessionStatus : int8_t { // The client should not retry the request. kNotClosable }; +std::string ToString(const CloseSessionStatus& status); std::ostream& operator<<(std::ostream& os, const CloseSessionStatus& status); -static const char* const SetSessionOptionStatusNames[] = { - "Unspecified", "Ok", "OkMapped", "InvalidName", "InvalidValue", "Error"}; -static const char* const CloseSessionStatusNames[] = {"Unspecified", "Closed", "Closing", - "NotClosable"}; - /// \brief A request to set a set of session options by name/value. struct ARROW_FLIGHT_EXPORT SetSessionOptionsRequest { std::map session_options; From 66310eba7eb4bf95590db27bed6c12fda93e33f3 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 20 Nov 2023 18:04:51 -0800 Subject: [PATCH 085/195] [builds] Return {"",NULLPTR} on id generation collision --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 6 +++++- cpp/src/arrow/flight/sql/server_session_middleware.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 276ccb0ad5ffa..592527627ccc1 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -163,13 +163,17 @@ Status ServerSessionMiddlewareFactory::StartCall( return Status::OK(); } -/// \brief Get a new, empty session option map and its id key. +/// \brief Get a new, empty session option map & its id key; {"",NULLPTR} on collision. std::pair> ServerSessionMiddlewareFactory::CreateNewSession() { auto new_id = id_generator_(); auto session = std::make_shared(); const std::lock_guard l(session_store_lock_); + if (session_store_.count(new_id)) { + // Collision + return {"", NULLPTR}; + } session_store_[new_id] = session; return {new_id, session}; diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index c74e1c81bae38..46268727a8873 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -59,6 +59,8 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware /// \brief Is there an existing session (either existing or new) virtual bool HasSession() const = 0; /// \brief Get existing or new call-associated session + /// + /// May return NULLPTR if there is an id generation collision. virtual std::shared_ptr GetSession() = 0; /// \brief Get request headers, in lieu of a provided or created session. virtual const CallHeaders& GetCallHeaders() const = 0; From e1a62faae90883d83db7187e611e4add54ceb490 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 20 Nov 2023 18:19:09 -0800 Subject: [PATCH 086/195] [builds] linter --- cpp/src/arrow/flight/types.cc | 2 +- cpp/src/arrow/flight/types.h | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index f5fb23c54d7de..31d57102ab1b8 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -525,7 +525,7 @@ template std::ostream& operator<<(std::ostream& os, std::map m) { os << '{'; std::string sep = ""; - if constexpr(std::is_convertible_v) { + if constexpr (std::is_convertible_v) { // std::string, char*, std::string_view for (const auto& [k, v] : m) { os << sep << '[' << k << "]: " << std::quoted(v) << '"'; diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 73f32d7e789c3..0a5913fc4bb57 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -841,9 +841,7 @@ struct ARROW_FLIGHT_EXPORT SetSessionOptionsResult { struct Result { SetSessionOptionStatus status; - bool Equals(const Result& other) const { - return status == other.status; - } + bool Equals(const Result& other) const { return status == other.status; } friend bool operator==(const Result& left, const Result& right) { return left.Equals(right); } From 71c1082286a1a5e14d2f959e358b8f822d3459e8 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 20 Nov 2023 18:57:24 -0800 Subject: [PATCH 087/195] [builds] copy to proto repeated string value using iterator --- cpp/src/arrow/flight/serialization_internal.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 4548e824ef53f..cc8083bd3c33c 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -431,8 +431,9 @@ Status ToProto(const SessionOptionValue& val, pb::SessionOptionValue* pb_val) { [&](float v) { pb_val->set_float_value(v); }, [&](double v) { pb_val->set_double_value(v); }, [&](std::vector v) { - auto* string_list_value = pb_val->mutable_string_list_value(); - for (const std::string& s : v) string_list_value->add_values(s); + auto* string_list_repeated_pointer_field = + pb_val->mutable_string_list_value()->mutable_values(); + string_list_repeated_pointer_field->Assign(v.begin(), v.end()); }}, val); return Status::OK(); From 0163d6ebdc46a3a163d3f293557c0650a4d391e5 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 20 Nov 2023 19:20:40 -0800 Subject: [PATCH 088/195] [builds] (partial?) fix for ParseCookieString, pending testing --- .../arrow/flight/sql/server_session_middleware.cc | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 592527627ccc1..701dcf9a9a2d4 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -102,16 +102,10 @@ ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { size_t cur = 0; while (cur < s.length()) { const size_t end = s.find(list_sep, cur); - size_t len; - if (end == std::string::npos) { - // No (further) list delimiters - len = std::string::npos; - cur = s.length(); - } else { - len = end - cur; - cur = end; - } + const bool further_pairs = end != std::string::npos; + const size_t len = further_pairs ? end - cur : std::string::npos; const std::string_view tok = s.substr(cur, len); + cur = further_pairs ? end + 2 : s.length(); const size_t val_pos = tok.find(pair_sep); if (val_pos == std::string::npos) { From 4e541f7a1f6188d7c83e6bf41f27ab86bc752833 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 20 Nov 2023 19:22:01 -0800 Subject: [PATCH 089/195] [builds] fixup --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 701dcf9a9a2d4..012a48249c0ac 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -105,7 +105,7 @@ ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { const bool further_pairs = end != std::string::npos; const size_t len = further_pairs ? end - cur : std::string::npos; const std::string_view tok = s.substr(cur, len); - cur = further_pairs ? end + 2 : s.length(); + cur = further_pairs ? end + list_sep.length() : s.length(); const size_t val_pos = tok.find(pair_sep); if (val_pos == std::string::npos) { From 4a3ea95ca5149641ff22d7f53b8776cc6c245d19 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 20 Nov 2023 19:23:07 -0800 Subject: [PATCH 090/195] [builds] fixup --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 012a48249c0ac..af9ba7e5083db 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -95,7 +95,6 @@ std::vector> ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { const std::string list_sep = "; "; const std::string pair_sep = "="; - const auto pair_sep_len = pair_sep.length(); std::vector> result; @@ -113,7 +112,7 @@ ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { continue; } result.emplace_back(tok.substr(0, val_pos), - tok.substr(val_pos + pair_sep_len, std::string::npos)); + tok.substr(val_pos + pair_sep.length(), std::string::npos)); } return result; From f29ea915c361464e8812d664b52bb355479e95e5 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 21 Nov 2023 12:21:55 -0800 Subject: [PATCH 091/195] [builds] grrrr CI grrrr --- cpp/src/arrow/flight/serialization_internal.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index cc8083bd3c33c..1b2897f78c18c 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -433,7 +433,7 @@ Status ToProto(const SessionOptionValue& val, pb::SessionOptionValue* pb_val) { [&](std::vector v) { auto* string_list_repeated_pointer_field = pb_val->mutable_string_list_value()->mutable_values(); - string_list_repeated_pointer_field->Assign(v.begin(), v.end()); + string_list_repeated_pointer_field->Add(v.begin(), v.end()); }}, val); return Status::OK(); From 4b9c13da005a6a69f9aa8a6092a8c208dc96fe90 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 21 Nov 2023 12:53:43 -0800 Subject: [PATCH 092/195] [builds] Revert iterator-copy not supported by CI PB libs --- cpp/src/arrow/flight/serialization_internal.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 1b2897f78c18c..4548e824ef53f 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -431,9 +431,8 @@ Status ToProto(const SessionOptionValue& val, pb::SessionOptionValue* pb_val) { [&](float v) { pb_val->set_float_value(v); }, [&](double v) { pb_val->set_double_value(v); }, [&](std::vector v) { - auto* string_list_repeated_pointer_field = - pb_val->mutable_string_list_value()->mutable_values(); - string_list_repeated_pointer_field->Add(v.begin(), v.end()); + auto* string_list_value = pb_val->mutable_string_list_value(); + for (const std::string& s : v) string_list_value->add_values(s); }}, val); return Status::OK(); From 8bc0de5ad2c1c52dc45b547628de3b051fe30bc2 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 22 Nov 2023 13:38:32 -0800 Subject: [PATCH 093/195] Add some testing --- cpp/src/arrow/flight/flight_internals_test.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cpp/src/arrow/flight/flight_internals_test.cc b/cpp/src/arrow/flight/flight_internals_test.cc index a1c5250ba66fa..a9faf40833119 100644 --- a/cpp/src/arrow/flight/flight_internals_test.cc +++ b/cpp/src/arrow/flight/flight_internals_test.cc @@ -331,6 +331,24 @@ TEST(FlightTypes, SchemaResult) { ASSERT_NO_FATAL_FAILURE(TestRoundtrip(values, reprs)); } +TEST(FlightTypes, SetSessionOptionsRequest) { + std::vector values = { + {}, + {{"foo", 3.0}}, + {{"foo", 3.0f}}, + {{"foo", 3.0}, {"bar": "3"}} + } + + std::vector reprs = { + "", + "", + "", + "" + } + + ASSERT_NO_FATAL_FAILURE(TestRoundTrip(values, reprs)); +} + TEST(FlightTypes, Ticket) { std::vector values = { {""}, From 3b82b7afa364026dd33fc1c23d43224c62940547 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 22 Nov 2023 14:14:13 -0800 Subject: [PATCH 094/195] oops --- cpp/src/arrow/flight/flight_internals_test.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/flight_internals_test.cc b/cpp/src/arrow/flight/flight_internals_test.cc index a9faf40833119..3880adb277732 100644 --- a/cpp/src/arrow/flight/flight_internals_test.cc +++ b/cpp/src/arrow/flight/flight_internals_test.cc @@ -337,14 +337,14 @@ TEST(FlightTypes, SetSessionOptionsRequest) { {{"foo", 3.0}}, {{"foo", 3.0f}}, {{"foo", 3.0}, {"bar": "3"}} - } + }; std::vector reprs = { "", "", "", "" - } + }; ASSERT_NO_FATAL_FAILURE(TestRoundTrip(values, reprs)); } From 6d48c72b26de42f2ad40281ec97c76ee469995ee Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 22 Nov 2023 14:39:07 -0800 Subject: [PATCH 095/195] grrr linter --- cpp/src/arrow/flight/flight_internals_test.cc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/src/arrow/flight/flight_internals_test.cc b/cpp/src/arrow/flight/flight_internals_test.cc index 3880adb277732..c10f2f1aa9700 100644 --- a/cpp/src/arrow/flight/flight_internals_test.cc +++ b/cpp/src/arrow/flight/flight_internals_test.cc @@ -333,17 +333,17 @@ TEST(FlightTypes, SchemaResult) { TEST(FlightTypes, SetSessionOptionsRequest) { std::vector values = { - {}, - {{"foo", 3.0}}, - {{"foo", 3.0f}}, - {{"foo", 3.0}, {"bar": "3"}} + {}, // comments + {{"foo", 3.0}}, // to + {{"foo", 3.0f}}, // silence + {{"foo", 3.0}, {"bar": "3"}} // linter }; std::vector reprs = { - "", - "", - "", - "" + "", + "", + "", + "" }; ASSERT_NO_FATAL_FAILURE(TestRoundTrip(values, reprs)); From bb52798ffe212c21f3fc81e12644f9e16c0734de Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 22 Nov 2023 14:48:42 -0800 Subject: [PATCH 096/195] grrr linter --- cpp/src/arrow/flight/flight_internals_test.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/src/arrow/flight/flight_internals_test.cc b/cpp/src/arrow/flight/flight_internals_test.cc index c10f2f1aa9700..6178b7cbaf7d8 100644 --- a/cpp/src/arrow/flight/flight_internals_test.cc +++ b/cpp/src/arrow/flight/flight_internals_test.cc @@ -333,17 +333,17 @@ TEST(FlightTypes, SchemaResult) { TEST(FlightTypes, SetSessionOptionsRequest) { std::vector values = { - {}, // comments - {{"foo", 3.0}}, // to - {{"foo", 3.0f}}, // silence - {{"foo", 3.0}, {"bar": "3"}} // linter + {}, + {{"foo", 3.0}}, + {{"foo", 3.0f}}, + {{"foo", 3.0}, {"bar": "3"}}, }; std::vector reprs = { "", "", "", - "" + "", }; ASSERT_NO_FATAL_FAILURE(TestRoundTrip(values, reprs)); From 92305734704b6d9112513d41ee681f949c92e840 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 22 Nov 2023 15:04:48 -0800 Subject: [PATCH 097/195] grrrr linter --- cpp/src/arrow/flight/flight_internals_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/flight_internals_test.cc b/cpp/src/arrow/flight/flight_internals_test.cc index 6178b7cbaf7d8..353d2eac66d43 100644 --- a/cpp/src/arrow/flight/flight_internals_test.cc +++ b/cpp/src/arrow/flight/flight_internals_test.cc @@ -336,7 +336,7 @@ TEST(FlightTypes, SetSessionOptionsRequest) { {}, {{"foo", 3.0}}, {{"foo", 3.0f}}, - {{"foo", 3.0}, {"bar": "3"}}, + {{"foo", 3.0}, {"bar", "3"}}, }; std::vector reprs = { From 02b599815299d8c22904eafe89fe1a8ce56cddcd Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 22 Nov 2023 16:31:40 -0800 Subject: [PATCH 098/195] grrrr linter --- cpp/src/arrow/flight/flight_internals_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/flight_internals_test.cc b/cpp/src/arrow/flight/flight_internals_test.cc index 353d2eac66d43..341f0ec4eda6e 100644 --- a/cpp/src/arrow/flight/flight_internals_test.cc +++ b/cpp/src/arrow/flight/flight_internals_test.cc @@ -339,7 +339,7 @@ TEST(FlightTypes, SetSessionOptionsRequest) { {{"foo", 3.0}, {"bar", "3"}}, }; - std::vector reprs = { + std::vector reprs = { "", "", "", From 01fd5597eb38119383d751f85a65521621ba2728 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 22 Nov 2023 23:13:50 -0800 Subject: [PATCH 099/195] [builds] Remove extraneous SessionOptions type tests --- cpp/src/arrow/flight/flight_internals_test.cc | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/cpp/src/arrow/flight/flight_internals_test.cc b/cpp/src/arrow/flight/flight_internals_test.cc index 341f0ec4eda6e..a1c5250ba66fa 100644 --- a/cpp/src/arrow/flight/flight_internals_test.cc +++ b/cpp/src/arrow/flight/flight_internals_test.cc @@ -331,24 +331,6 @@ TEST(FlightTypes, SchemaResult) { ASSERT_NO_FATAL_FAILURE(TestRoundtrip(values, reprs)); } -TEST(FlightTypes, SetSessionOptionsRequest) { - std::vector values = { - {}, - {{"foo", 3.0}}, - {{"foo", 3.0f}}, - {{"foo", 3.0}, {"bar", "3"}}, - }; - - std::vector reprs = { - "", - "", - "", - "", - }; - - ASSERT_NO_FATAL_FAILURE(TestRoundTrip(values, reprs)); -} - TEST(FlightTypes, Ticket) { std::vector values = { {""}, From 28c9b319af9ca0d2f1e29186e9b99feffa997c6d Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 29 Nov 2023 11:36:41 -0800 Subject: [PATCH 100/195] Typo fix --- cpp/src/arrow/flight/types.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 31d57102ab1b8..feb9f1a11eb65 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -986,17 +986,17 @@ const ActionType ActionType::kSetSessionOptions = ActionType{"SetSessionOptions", "Set client session options by name/value pairs.\n" "Request Message: SetSessionOptionsRequest\n" - "Response Message: SetSessionOptionsResult\n"}; + "Response Message: SetSessionOptionsResult"}; const ActionType ActionType::kGetSessionOptions = ActionType{"GetSessionOptions", "Get current client session options\n" "Request Message: GetSessionOptionsRequest\n" - "Response Message: GetSessionOptionsResult\n"}; + "Response Message: GetSessionOptionsResult"}; const ActionType ActionType::kCloseSession = ActionType{"CloseSession", "Explicitly close/invalidate the cookie-specified client session.\n" "Request Message: CloseSessionRequest\n" - "Response Message: CloseSessionResult\n"}; + "Response Message: CloseSessionResult"}; bool ActionType::Equals(const ActionType& other) const { return type == other.type && description == other.description; From 44cb613fa3fc578dc327bee163d18a8b733e8e98 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 29 Nov 2023 15:04:19 -0800 Subject: [PATCH 101/195] [Java WIP] Add ActionTypes & some SessionOptionValue types --- .../apache/arrow/flight/FlightConstants.java | 14 +++ .../arrow/flight/SessionOptionValue.java | 22 ++++ .../flight/SessionOptionValueFactory.java | 106 ++++++++++++++++++ .../flight/SessionOptionValueVisitor.java | 34 ++++++ 4 files changed, 176 insertions(+) create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightConstants.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightConstants.java index 2a240abad6d95..0386bae4bf9a0 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightConstants.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightConstants.java @@ -35,4 +35,18 @@ public interface FlightConstants { "Extend expiration time of the given FlightEndpoint.\n" + "Request Message: RenewFlightEndpointRequest\n" + "Response Message: Renewed FlightEndpoint"); + + ActionType SET_SESSION_OPTIONS = new ActionType("SetSessionOptions", + "Set client session options by name/value pairs.\n" + "Request Message: SetSessionOptionsRequest\n" + "Response Message: SetSessionOptionsResult"); + + ActionType GET_SESSION_OPTIONS = new ActionType("GetSessionOptions", + "Get current client session options\n" + "Request Message: GetSessionOptionsRequest\n" + "Response Message: GetSessionOptionsResult"); + ActionType CLOSE_SESSION = new ActionType("CloseSession", + "Explicitly close/invalidate the cookie-specified client session.\n" + "Request Message: CloseSessionRequest\n" + "Response Message: CloseSessionResult"); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java new file mode 100644 index 0000000000000..4ddbf2538c7c0 --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -0,0 +1,22 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +public interface SessionOptionValue { + void visit(SessionOptionValueVisitor); +} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java new file mode 100644 index 0000000000000..8a1c90a0771ee --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +import org.apache.arrow.flight.SessionOptionValue; + +public class SessionOptionValueFactory { + public static SessionOptionValue makeSessionOption(String value) { + return new SessionOptionValueString(value); + } + + public static SessionOptionValue makeSessionOption(bool value) { + return new SessionOptionValueBool(value); + } + + public static SessionOptionValue makeSessionOption(int value) { + return new SessionOptionValueInt(value); + } + + public static SessionOptionValue makeSessionOption(long value) { + return new SessionOptionValueLong(value); + } + + public static SessionOptionValue makeSessionOption(float value) { + return new SessionOptionValueFloat(value); + } + + public static SessionOptionValue makeSessionOption(double value) { + return new SessionOptionValueDouble(value); + } + + public static SessionOptionValue makeSessionOption(String[] value) { + return new SessionOptionValueStringList(value); + } +} + +class SessionOptionValueString { + private final String value; + + SessionOptionValue(String value) { + this.value = value; + } +} + +class SessionOptionValueBool { + private final boolean value; + + SessionOptionValue(boolean value) { + this.value = value; + } +} + +class SessionOptionValueInt { + private final int value; + + SessionOptionValue(int value) { + this.value = value; + } +} + +class SessionOptionValueLong { + private final long value; + + SessionOptionValue(long value) { + this.value = value; + } +} + +class SessionOptionValueFloat { + private final float value; + + SessionOptionValue(Float value) { + this.value = value; + } +} + + +class SessionOptionValueDouble { + private final double value; + + SessionOptionValue(double value) { + this.value = value; + } +} +class SessionOptionValueStringList { + private final String[] value; + + SessionOptionValue(String[] value) { + this.value = value.clone(); + } +} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java new file mode 100644 index 0000000000000..9a0804114eda0 --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java @@ -0,0 +1,34 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +public interface SessionOptionValueVisitor { + void visit(String value); + + void visit(boolean value); + + void visit(int value); + + void visit(long value); + + void visit(float value); + + void visit(double value); + + void visit(String[] value); +} From 7e5b5c223b5cdfc880bc603d1c7d1cc6224b78d4 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 29 Nov 2023 15:10:07 -0800 Subject: [PATCH 102/195] +some docs --- .../flight/SessionOptionValueVisitor.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java index 9a0804114eda0..a69fbeac73328 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java @@ -17,18 +17,49 @@ package org.apache.arrow.flight; +/** + * A visitor interface to access SessionOptionValue's contained value. + */ public interface SessionOptionValueVisitor { + /** + * Callback to handle SessionOptionValue containing a String. + * @param value The contained value being accessed. + */ void visit(String value); + /** + * Callback to handle SessionOptionValue containing a boolean. + * @param value The contained value being accessed. + */ void visit(boolean value); + /** + * Callback to handle SessionOptionValue containing an int. + * @param value The contained value being accessed. + */ void visit(int value); + /** + * Callback to handle SessionOptionValue containing a long. + * @param value The contained value being accessed. + */ void visit(long value); + /** + * Callback to handle SessionOptionValue containing a float. + * @param value The contained value being accessed. + */ void visit(float value); + /** + * Callback to handle SessionOptionValue containing a double. + * @param value The contained value being accessed. + */ void visit(double value); + /** + * Callback to handle SessionOptionValue containing an array of String. + * @param value The contained value being accessed. + */ void visit(String[] value); } From b6eca04daeb76fead319882e9d638b1ab65462bb Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 29 Nov 2023 15:11:35 -0800 Subject: [PATCH 103/195] +some docs --- .../arrow/flight/SessionOptionValue.java | 6 ++++++ .../flight/SessionOptionValueVisitor.java | 21 +++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index 4ddbf2538c7c0..87c8fb5b2943d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -17,6 +17,12 @@ package org.apache.arrow.flight; +/** + * A container + */ public interface SessionOptionValue { + /** + * + */ void visit(SessionOptionValueVisitor); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java index a69fbeac73328..f502e78fb5635 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java @@ -22,44 +22,37 @@ */ public interface SessionOptionValueVisitor { /** - * Callback to handle SessionOptionValue containing a String. - * @param value The contained value being accessed. + * A callback to handle SessionOptionValue containing a String. */ void visit(String value); /** - * Callback to handle SessionOptionValue containing a boolean. - * @param value The contained value being accessed. + * A callback to handle SessionOptionValue containing a boolean. */ void visit(boolean value); /** - * Callback to handle SessionOptionValue containing an int. - * @param value The contained value being accessed. + * A callback to handle SessionOptionValue containing an int. */ void visit(int value); /** - * Callback to handle SessionOptionValue containing a long. - * @param value The contained value being accessed. + * A callback to handle SessionOptionValue containing a long. */ void visit(long value); /** - * Callback to handle SessionOptionValue containing a float. - * @param value The contained value being accessed. + * A callback to handle SessionOptionValue containing a float. */ void visit(float value); /** - * Callback to handle SessionOptionValue containing a double. - * @param value The contained value being accessed. + * A callback to handle SessionOptionValue containing a double. */ void visit(double value); /** - * Callback to handle SessionOptionValue containing an array of String. - * @param value The contained value being accessed. + * A callback to handle SessionOptionValue containing an array of String. */ void visit(String[] value); } From 8d72dde787ae8503889093dab249096bbcea9e0c Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 29 Nov 2023 15:21:54 -0800 Subject: [PATCH 104/195] +some docs --- .../main/java/org/apache/arrow/flight/SessionOptionValue.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index 87c8fb5b2943d..ba765540fcc90 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -18,11 +18,11 @@ package org.apache.arrow.flight; /** - * A container + * A union-like container interface for supported session option value types. */ public interface SessionOptionValue { /** - * + * Value access via a caller-provided visitor/functor. */ void visit(SessionOptionValueVisitor); } From 35852fd97b5d892a01007b41571c78d5c8160511 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 1 Dec 2023 15:32:34 -0800 Subject: [PATCH 105/195] Add some partially/fully implemented POJO message types --- cpp/src/arrow/flight/types.h | 2 +- format/Flight.proto | 20 +-- .../arrow/flight/CloseSessionRequest.java | 54 ++++++++ .../arrow/flight/CloseSessionResult.java | 117 ++++++++++++++++++ .../flight/GetSessionOptionsRequest.java | 54 ++++++++ .../arrow/flight/GetSessionOptionsResult.java | 62 ++++++++++ .../arrow/flight/SessionOptionValue.java | 45 +++++++ .../flight/SetSessionOptionsRequest.java | 73 +++++++++++ .../arrow/flight/SetSessionOptionsResult.java | 98 +++++++++++++++ .../arrow/flight/sql/FlightSqlProducer.java | 3 + 10 files changed, 517 insertions(+), 11 deletions(-) create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 0a5913fc4bb57..5d63191160714 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -774,7 +774,7 @@ enum class SetSessionOptionStatus : int8_t { /// \brief The status of setting the option is unknown. /// /// Servers should avoid using this value (send a NOT_FOUND error if the requested - /// query is not known). Clients can retry the request. + /// session is not known). Clients can retry the request. kUnspecified, // The session option setting completed successfully. kOk, diff --git a/format/Flight.proto b/format/Flight.proto index dab0ffaa30658..f4b0042020dcb 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -564,17 +564,17 @@ message SetSessionOptionsResult { // The status of setting the option is unknown. Servers should avoid using // this value (send a NOT_FOUND error if the requested query is // not known). Clients can retry the request. - SET_SESSION_OPTION_RESULT_UNSPECIFIED = 0; + UNSPECIFIED = 0; // The session option setting completed successfully. - SET_SESSION_OPTION_RESULT_OK = 1; + OK = 1; // The given session option name was an alias for another option name. - SET_SESSION_OPTION_RESULT_OK_MAPPED = 2; + OK_MAPPED = 2; // The given session option name is invalid. - SET_SESSION_OPTION_RESULT_INVALID_NAME = 3; + INVALID_NAME = 3; // The session option value is invalid. - SET_SESSION_OPTION_RESULT_INVALID_VALUE = 4; + INVALID_VALUE = 4; // The session option cannot be set. - SET_SESSION_OPTION_RESULT_ERROR = 5; + ERROR = 5; } message Result { @@ -616,16 +616,16 @@ message CloseSessionResult { // The session close status is unknown. Servers should avoid using // this value (send a NOT_FOUND error if the requested session is // not known). Clients can retry the request. - CLOSE_RESULT_UNSPECIFIED = 0; + UNSPECIFIED = 0; // The session close request is complete. Subsequent requests with // the same session produce a NOT_FOUND error. - CLOSE_RESULT_CLOSED = 1; + CLOSED = 1; // The session close request is in progress. The client may retry // the close request. - CLOSE_RESULT_CLOSING = 2; + CLOSING = 2; // The session is not closeable. The client should not retry the // close request. - CLOSE_RESULT_NOT_CLOSEABLE = 3; + NOT_CLOSEABLE = 3; } Status status = 1; diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java new file mode 100644 index 0000000000000..5f17348c9e5a8 --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java @@ -0,0 +1,54 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public class CloseSessionRequest { + public CloseSessionRequest() {} + + CloseSessionRequest(Flight.CloseSessionRequest proto) {} + + Flight.CloseSessionRequest toProtocol() { + Flight.CloseSessionRequest.Builder b = Flight.CloseSessionRequest.newBuilder(); + return b.build(); + } + + /** + * Get the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing non-Flight services to still return Flight types. + */ + public ByteBuffer serialize() { + return ByteBuffer.wrap(toProtocol().toByteArray()); + } + + /** + * Parse the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing Flight clients to obtain stream info from non-Flight services. + * + * @param serialized The serialized form of the message, as returned by {@link #serialize()}. + * @return The deserialized message. + * @throws IOException if the serialized form is invalid. + */ + public static CloseSessionRequest deserialize(ByteBuffer serialized) throws IOException { + return new CloseSessionRequest(Flight.CloseSessionRequest.parseFrom(serialized)); + } +} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java new file mode 100644 index 0000000000000..8c70731a55128 --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java @@ -0,0 +1,117 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public class CloseSessionResult { + public enum Status { + /** + * The session close status is unknown. Servers should avoid using this value + * (send a NOT_FOUND error if the requested session is not known). Clients can + * retry the request. + */ + UNSPECIFIED, + /** + * The session close request is complete. + */ + CLOSED, + /** + * The session close request is in progress. The client may retry the request. + */ + CLOSING, + /** + * The session is not closeable. + */ + NOT_CLOSABLE, + ; + } + + private final Status status; + + public CloseSessionResult(Status status) { + this.status = status; + } + + CloseSessionResult(Flight.CloseSessionResult proto) { + switch (proto.getStatus()) { + case UNSPECIFIED: + status = Status.UNSPECIFIED; + break; + case CLOSED: + status = Status.CLOSED; + break; + case CLOSING: + status = Status.CLOSING; + break; + case NOT_CLOSABLE: + status = Status.NOT_CLOSABLE; + break; + default: + // Unreachable + throw new IllegalArgumentException(""); + } + } + + + Flight.CloseSessionResult toProtocol() { + Flight.CloseSessionResult.Builder b = Flight.CloseSessionResult.newBuilder(); + switch (status) { + case UNSPECIFIED: + b.setStatus(Flight.CloseSessionResult.Status.UNSPECIFIED); + break; + case CLOSED: + b.setStatus(Flight.CloseSessionResult.Status.CLOSED); + break; + case CLOSING: + b.setStatus(Flight.CloseSessionResult.Status.CLOSING); + break; + case NOT_CLOSABLE: + b.setStatus(Flight.CloseSessionResult.Status.NOT_CLOSABLE); + break; + default: + // Unreachable + throw new IllegalStateException(""); + } + return b.build(); + } + + /** + * Get the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing non-Flight services to still return Flight types. + */ + public ByteBuffer serialize() { + return ByteBuffer.wrap(toProtocol().toByteArray()); + } + + /** + * Parse the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing Flight clients to obtain stream info from non-Flight services. + * + * @param serialized The serialized form of the message, as returned by {@link #serialize()}. + * @return The deserialized message. + * @throws IOException if the serialized form is invalid. + */ + public static CloseSessionResult deserialize(ByteBuffer serialized) throws IOException { + return new CloseSessionResult(Flight.CloseSessionResult.parseFrom(serialized)); + } + +} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java new file mode 100644 index 0000000000000..a98ec8ce4b379 --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java @@ -0,0 +1,54 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public class GetSessionOptionsRequest { + public GetSessionOptionsRequest() {} + + GetSessionOptionsRequest(Flight.GetSessionOptionsRequest proto) {} + + Flight.GetSessionOptionsRequest toProtocol() { + Flight.GetSessionOptionsRequest.Builder b = Flight.GetSessionOptionsRequest.newBuilder(); + return b.build(); + } + + /** + * Get the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing non-Flight services to still return Flight types. + */ + public ByteBuffer serialize() { + return ByteBuffer.wrap(toProtocol().toByteArray()); + } + + /** + * Parse the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing Flight clients to obtain stream info from non-Flight services. + * + * @param serialized The serialized form of the message, as returned by {@link #serialize()}. + * @return The deserialized message. + * @throws IOException if the serialized form is invalid. + */ + public static GetSessionOptionsRequest deserialize(ByteBuffer serialized) throws IOException { + return new GetSessionOptionsRequest(Flight.GetSessionOptionsRequest.parseFrom(serialized)); + } +} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java new file mode 100644 index 0000000000000..e42f0a11dc622 --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java @@ -0,0 +1,62 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +import java.io.IOException; +import java.nio.ByteBuffer; + +public class GetSessionOptionsResult { + private final Map session_options; + + public GetSessionOptionsResult(Map session_options) { + this.session_options = new HashMap(session_options); + } + + GetSessionOptionsResult(Flight.GetSessionOptionsResult proto) { + // PHOXME impl + } + + Flight.GetSessionOptionsResult toProtocol() { + Flight.GetSessionOptionsResult.Builder b = Flight.GetSessionOptionsResult.newBuilder(); + // FIXME impl + b.putAllSessionOptions(); + return b.build(); + } + + /** + * Get the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing non-Flight services to still return Flight types. + */ + public ByteBuffer serialize() { + return ByteBuffer.wrap(toProtocol().toByteArray()); + } + + /** + * Parse the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing Flight clients to obtain stream info from non-Flight services. + * + * @param serialized The serialized form of the message, as returned by {@link #serialize()}. + * @return The deserialized message. + * @throws IOException if the serialized form is invalid. + */ + public static GetSessionOptionsResult deserialize(ByteBuffer serialized) throws IOException { + return new GetSessionOptionsResult(Flight.GetSessionOptionsResult.parseFrom(serialized)); + } +} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index ba765540fcc90..ea6c67a660a00 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -17,6 +17,8 @@ package org.apache.arrow.flight; +import org.apache.arrow.flight.impl.Flight; + /** * A union-like container interface for supported session option value types. */ @@ -25,4 +27,47 @@ public interface SessionOptionValue { * Value access via a caller-provided visitor/functor. */ void visit(SessionOptionValueVisitor); + + Flight.SessionOptionValue toProtocol() { + Flight.SessionOptionValue.Builder b = Flight.SessionOptionValue.newBuilder(); + SessionOptionValueToProtocolVisitor visitor = new SessionOptionValueToProtocolVisitor(b); + this.visit(visitor); + return b.build(); + } } + +class SessionOptionValueToProtocolVisitor implements SessionOptionValueVisitor { + final Flight.SessionOptionValue.Builder b; + + SessionOptionValueVisitor(Flight.SessionOptionValue.Builder b) { this.b = b; } + + Flight.SessionOptionValue visit(String value) { + b.setStringValue(value); + } + + Flight.SessionOptionValue visit(boolean value) { + b.setBoolValue(value); + } + + Flight.SessionOptionValue visit(int value) { + b.setIn32Value(value); + } + + Flight.SessionOptionValue visit(long value) { + b.setInt64Value(value); + } + + Flight.SessionOptionValue visit(float value) { + b.setFloatValue(value); + } + + Flight.SessionOptionValue visit(double value) { + b.setDoubleValue(value); + } + + Flight.SessionOptionValue visit(String[] value) { + Flight.SessionOptionValue.StringListValue pb_value; + pb_value.addAllStringValues(value); + b.setValue(pb_value); + } +} \ No newline at end of file diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java new file mode 100644 index 0000000000000..8c871b98b4e38 --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java @@ -0,0 +1,73 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.Map; + +public class SetSessionOptionsRequest { + private final Map session_options; + + public SetSessionOptionsRequest(Map session_options) { + this.session_options = ConcurrentHashMap(session_options); + } + + SetSessionOptionsRequest(Flight.SetSessionOptionsRequest proto) { + // FIXME impl + } + + /** + * + * @return An immutable view of the session options map. + */ + public Map getSessionOptions() { + return new Collections.unmodifiableMap(session_options); + } + + Flight.SetSessionOptionsRequest toProtocol() { + Flight.SetSessionOptionsRequest.Builder b = Flight.SetSessionOptionsRequest.newBuilder(); + // FIXME impl + return b.build(); + } + + /** + * Get the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing non-Flight services to still return Flight types. + */ + public ByteBuffer serialize() { + return ByteBuffer.wrap(toProtocol().toByteArray()); + } + + /** + * Parse the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing Flight clients to obtain stream info from non-Flight services. + * + * @param serialized The serialized form of the message, as returned by {@link #serialize()}. + * @return The deserialized message. + * @throws IOException if the serialized form is invalid. + */ + public static SetSessionOptionsRequest deserialize(ByteBuffer serialized) throws IOException { + return new SetSessionOptionsRequest(Flight.SetSessionOptionsRequest.parseFrom(serialized)); + } + +} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java new file mode 100644 index 0000000000000..4c65c7ba1428e --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -0,0 +1,98 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.Map; + +public class SetSessionOptionsResult { + public enum Status { + /** + * The status of setting the option is unknown. Servers should avoid using this value + * (send a NOT_FOUND error if the requested session is not known). Clients can retry + * the request. + */ + UNSPECIFIED, + /** + * The session option setting completed successfully. + */ + OK, + /** + * The given session option name was an alias for another option name. + */ + OK_MAPPED, + /** + * The given session option name is invalid. + */ + INVALID_NAME, + /** + * The session option value is invalid. + */ + INVALID_VALUE, + /** + * The session option cannot be set. + */ + ERROR, + ; + } + + private final Map results; + + public SetSessionOptionsResult(Map results) { + this.results = HashMap(results); + } + + SetSessionOptionsResult(Flight.SetSessionOptionsResult proto) { + // PHOXME impl + } + + Map getResults() { + return Collections.unmodifiableMap(results); + } + + Flight.SetSessionOptionsResult toProtocol() { + Flight.SetSessionOptionsResult.Builder b = Flight.SetSessionOptionsResult.newBuilder(); + // PHOXME impl + return b.build(); + } + + /** + * Get the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing non-Flight services to still return Flight types. + */ + public ByteBuffer serialize() { + return ByteBuffer.wrap(toProtocol().toByteArray()); + } + + /** + * Parse the serialized form of this protocol message. + * + *

Intended to help interoperability by allowing Flight clients to obtain stream info from non-Flight services. + * + * @param serialized The serialized form of the message, as returned by {@link #serialize()}. + * @return The deserialized message. + * @throws IOException if the serialized form is invalid. + */ + public static SetSessionOptionsResult deserialize(ByteBuffer serialized) throws IOException { + return new SetSessionOptionsResult(Flight.SetSessionOptionsResult.parseFrom(serialized)); + } + +} diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java index dbe39ab1d07b4..4230903b25dd4 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java @@ -56,16 +56,19 @@ import org.apache.arrow.flight.CallStatus; import org.apache.arrow.flight.CancelFlightInfoRequest; import org.apache.arrow.flight.CancelStatus; +import org.apache.arrow.flight.CloseSessionRequest; import org.apache.arrow.flight.FlightConstants; import org.apache.arrow.flight.FlightDescriptor; import org.apache.arrow.flight.FlightEndpoint; import org.apache.arrow.flight.FlightInfo; import org.apache.arrow.flight.FlightProducer; import org.apache.arrow.flight.FlightStream; +import org.apache.arrow.flight.GetSessionOptionsRequest; import org.apache.arrow.flight.PutResult; import org.apache.arrow.flight.RenewFlightEndpointRequest; import org.apache.arrow.flight.Result; import org.apache.arrow.flight.SchemaResult; +import org.apache.arrow.flight.SetSessionOptionsRequest; import org.apache.arrow.flight.Ticket; import org.apache.arrow.flight.sql.impl.FlightSql.ActionClosePreparedStatementRequest; import org.apache.arrow.flight.sql.impl.FlightSql.ActionCreatePreparedStatementRequest; From 5de14558efe778c6854048c84c673911c74933e3 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 1 Dec 2023 16:11:36 -0800 Subject: [PATCH 106/195] Add method skeleton --- .../main/java/org/apache/arrow/flight/SessionOptionValue.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index ea6c67a660a00..05531bb8fe07d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -23,6 +23,10 @@ * A union-like container interface for supported session option value types. */ public interface SessionOptionValue { + SessionOptionValue(Flight.SessionOptionValue) { + // TODO PHOXME impl + } + /** * Value access via a caller-provided visitor/functor. */ From 67b1a7faaf052d7a059b3cfafdf30cb3160c9ca7 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 5 Dec 2023 16:24:53 -0800 Subject: [PATCH 107/195] WIP: Java: add serde + POJO classes --- .../arrow/flight/CloseSessionResult.java | 65 ++++++------- .../arrow/flight/GetSessionOptionsResult.java | 25 +++-- .../arrow/flight/SessionOptionValue.java | 36 ++++--- .../flight/SessionOptionValueFactory.java | 94 +++++++++++++++---- .../flight/SetSessionOptionsRequest.java | 17 ++-- .../arrow/flight/SetSessionOptionsResult.java | 48 +++++++--- 6 files changed, 186 insertions(+), 99 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java index 8c70731a55128..95c25a2cf54ee 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java @@ -27,20 +27,40 @@ public enum Status { * (send a NOT_FOUND error if the requested session is not known). Clients can * retry the request. */ - UNSPECIFIED, + UNSPECIFIED(Flight.CloseSessionResult.Status.UNSPECIFIED), /** * The session close request is complete. */ - CLOSED, + CLOSED(Flight.CloseSessionResult.Status.CLOSED), /** * The session close request is in progress. The client may retry the request. */ - CLOSING, + CLOSING(Flight.CloseSessionResult.Status.CLOSING), /** * The session is not closeable. */ - NOT_CLOSABLE, + NOT_CLOSABLE(Flight.CloseSessionResult.Status.NOT_CLOSABLE), ; + + private static final Map mapFromProto; + + static { + for (Status s : values()) mapFromProto.put(s.proto, s); + } + + private final Flight.CloseSessionResult.Status proto; + + private Status(Flight.CloseSessionResult.Status s) { + proto = s; + } + + public static Status fromProtocol(Flight.CloseSessionResult.Status s) { + return mapFromProto.get(s); + } + + public Flight.CloseSessionResult.Status toProtocol() { + return proto; + } } private final Status status; @@ -50,45 +70,20 @@ public CloseSessionResult(Status status) { } CloseSessionResult(Flight.CloseSessionResult proto) { - switch (proto.getStatus()) { - case UNSPECIFIED: - status = Status.UNSPECIFIED; - break; - case CLOSED: - status = Status.CLOSED; - break; - case CLOSING: - status = Status.CLOSING; - break; - case NOT_CLOSABLE: - status = Status.NOT_CLOSABLE; - break; - default: + status = Status.fromProtocol(proto.getStatus()); + if (status == null) { // Unreachable throw new IllegalArgumentException(""); } } + Status getStatus() { + return status; + } Flight.CloseSessionResult toProtocol() { Flight.CloseSessionResult.Builder b = Flight.CloseSessionResult.newBuilder(); - switch (status) { - case UNSPECIFIED: - b.setStatus(Flight.CloseSessionResult.Status.UNSPECIFIED); - break; - case CLOSED: - b.setStatus(Flight.CloseSessionResult.Status.CLOSED); - break; - case CLOSING: - b.setStatus(Flight.CloseSessionResult.Status.CLOSING); - break; - case NOT_CLOSABLE: - b.setStatus(Flight.CloseSessionResult.Status.NOT_CLOSABLE); - break; - default: - // Unreachable - throw new IllegalStateException(""); - } + b.setStatus(status.toProtocol()): return b.build(); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java index e42f0a11dc622..0df5053c92750 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java @@ -19,22 +19,35 @@ import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; public class GetSessionOptionsResult { - private final Map session_options; + private final Map sessionOptions; - public GetSessionOptionsResult(Map session_options) { - this.session_options = new HashMap(session_options); + public GetSessionOptionsResult(Map sessionOptions) { + this.sessionOptions = Collections.unmodifiableMap(new HashMap(sessionOptions)); } GetSessionOptionsResult(Flight.GetSessionOptionsResult proto) { - // PHOXME impl + sessionOptions = Collections.unmodifiableMap( + proto.getSessionOptions().entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, (e) -> SessionOptionValueFactory.makeSessionOptionValue(e.getValue())))); + } + + /** + * + * @return An immutable view of the session options map. + */ + public Map getSessionOptions() { + return new sessionOptions; } Flight.GetSessionOptionsResult toProtocol() { Flight.GetSessionOptionsResult.Builder b = Flight.GetSessionOptionsResult.newBuilder(); - // FIXME impl - b.putAllSessionOptions(); + b.putAllSessionOptions(sessionOptions.entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, (e) -> e.getValue().toProtocol()))); return b.build(); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index 05531bb8fe07d..8ff85af6788cf 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -17,25 +17,23 @@ package org.apache.arrow.flight; +import java.util.stream.Collectors; + import org.apache.arrow.flight.impl.Flight; /** * A union-like container interface for supported session option value types. */ -public interface SessionOptionValue { - SessionOptionValue(Flight.SessionOptionValue) { - // TODO PHOXME impl - } - +public abstract class SessionOptionValue { /** * Value access via a caller-provided visitor/functor. */ - void visit(SessionOptionValueVisitor); + abstract void acceptVisitor(SessionOptionValueVisitor); Flight.SessionOptionValue toProtocol() { Flight.SessionOptionValue.Builder b = Flight.SessionOptionValue.newBuilder(); SessionOptionValueToProtocolVisitor visitor = new SessionOptionValueToProtocolVisitor(b); - this.visit(visitor); + this.acceptVisitor(visitor); return b.build(); } } @@ -45,33 +43,31 @@ class SessionOptionValueToProtocolVisitor implements SessionOptionValueVisitor { SessionOptionValueVisitor(Flight.SessionOptionValue.Builder b) { this.b = b; } - Flight.SessionOptionValue visit(String value) { + void visit(String value) { b.setStringValue(value); } - Flight.SessionOptionValue visit(boolean value) { - b.setBoolValue(value); - } + void visit(boolean value) { b.setBoolValue(value); } - Flight.SessionOptionValue visit(int value) { + void visit(int value) { b.setIn32Value(value); } - Flight.SessionOptionValue visit(long value) { + void visit(long value) { b.setInt64Value(value); } - Flight.SessionOptionValue visit(float value) { + void visit(float value) { b.setFloatValue(value); } - Flight.SessionOptionValue visit(double value) { + void visit(double value) { b.setDoubleValue(value); } - Flight.SessionOptionValue visit(String[] value) { - Flight.SessionOptionValue.StringListValue pb_value; - pb_value.addAllStringValues(value); - b.setValue(pb_value); + void visit(String[] value) { + Flight.SessionOptionValue.StringListValue pbValue; + pbValue.addAllStringValues(value); + b.setValue(pbValue); } -} \ No newline at end of file +} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 8a1c90a0771ee..08d7720fdcd16 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -17,90 +17,144 @@ package org.apache.arrow.flight; +import java.util.stream.Collectors; + import org.apache.arrow.flight.SessionOptionValue; public class SessionOptionValueFactory { - public static SessionOptionValue makeSessionOption(String value) { + public static SessionOptionValue makeSessionOptionValue(String value) { return new SessionOptionValueString(value); } - public static SessionOptionValue makeSessionOption(bool value) { + public static SessionOptionValue makeSessionOptionValue(bool value) { return new SessionOptionValueBool(value); } - public static SessionOptionValue makeSessionOption(int value) { + public static SessionOptionValue makeSessionOptionValue(int value) { return new SessionOptionValueInt(value); } - public static SessionOptionValue makeSessionOption(long value) { + public static SessionOptionValue makeSessionOptionValue(long value) { return new SessionOptionValueLong(value); } - public static SessionOptionValue makeSessionOption(float value) { + public static SessionOptionValue makeSessionOptionValue(float value) { return new SessionOptionValueFloat(value); } - public static SessionOptionValue makeSessionOption(double value) { + public static SessionOptionValue makeSessionOptionValue(double value) { return new SessionOptionValueDouble(value); } - public static SessionOptionValue makeSessionOption(String[] value) { + public static SessionOptionValue makeSessionOptionValue(String[] value) { return new SessionOptionValueStringList(value); } + + public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValue proto) { + switch(proto.getOptionValueCase()) { + case STRING_VALUE: + return new SessionOptionValueString(proto.getStringValue()); + case BOOL_VALUE: + return new SessionOptionValueBoolean(proto.getValue()); + case INT32_VALUE: + return new SessionOptionValueInteger(proto.getInt32Value()); + case INT64_VALUE: + return new SessionOptionValueLong(proto.getInt64Value()); + case FLOAT_VALUE: + return new SessionOptionValueFloat(proto.getFloatValue()); + case DOUBLE_VALUE: + return new SessionOptionValueDouble(proto.getDoubleValue()); + case STRING_LIST_VALUE: + // FIXME PHOXME is this what's in the ProtocolStringList? + return new SessionOptionValueStringList(proto.getValueStringList().stream().collect( + Collectors.toList(e -> google.protocol.StringValue.parseFrom(e).getValue()))); + default: + // Unreachable + throw new IllegalArgumentException(""); + } + } } -class SessionOptionValueString { +class SessionOptionValueString extends SessionOptionvalue { private final String value; SessionOptionValue(String value) { this.value = value; } + + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -class SessionOptionValueBool { +class SessionOptionValueBoolean extends SessionOptionvalue { private final boolean value; - SessionOptionValue(boolean value) { + SessionOptionValueBoolean(boolean value) { this.value = value; } + + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -class SessionOptionValueInt { +class SessionOptionValueInt extends SessionOptionvalue { private final int value; - SessionOptionValue(int value) { + SessionOptionValueInt(int value) { this.value = value; } + + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -class SessionOptionValueLong { +class SessionOptionValueLong extends SessionOptionvalue { private final long value; - SessionOptionValue(long value) { + SessionOptionValueLong(long value) { this.value = value; } + + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -class SessionOptionValueFloat { +class SessionOptionValueFloat extends SessionOptionvalue { private final float value; - SessionOptionValue(Float value) { + SessionOptionValueFloat(Float value) { this.value = value; } + + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -class SessionOptionValueDouble { +class SessionOptionValueDouble extends SessionOptionvalue { private final double value; - SessionOptionValue(double value) { + SessionOptionValueDouble(double value) { this.value = value; } + + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -class SessionOptionValueStringList { +class SessionOptionValueStringList extends SessionOptionvalue { private final String[] value; - SessionOptionValue(String[] value) { + SessionOptionValueStringList(String[] value) { this.value = value.clone(); } + + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java index 8c871b98b4e38..5839d9fa044e0 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java @@ -18,20 +18,22 @@ package org.apache.arrow.flight; import java.io.IOException; -import java.net.URISyntaxException; import java.nio.ByteBuffer; import java.util.Collections; import java.util.Map; +import java.util.stream.Collectors; public class SetSessionOptionsRequest { - private final Map session_options; + private final Map sessionOptions; - public SetSessionOptionsRequest(Map session_options) { - this.session_options = ConcurrentHashMap(session_options); + public SetSessionOptionsRequest(Map sessionOptions) { + this.sessionOptions = Collections.unmodifiableMap(new HashMap(sessionOptions)); } SetSessionOptionsRequest(Flight.SetSessionOptionsRequest proto) { - // FIXME impl + sessionOptions = Collections.unmodifiableMap( + proto.getSessionOptions().entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, (e) -> SessionOptionValueFactory.makeSessionOptionValue(e.getValue())))); } /** @@ -39,12 +41,13 @@ public SetSessionOptionsRequest(Map session_options) * @return An immutable view of the session options map. */ public Map getSessionOptions() { - return new Collections.unmodifiableMap(session_options); + return new Collections.unmodifiableMap(sessionOptions); } Flight.SetSessionOptionsRequest toProtocol() { Flight.SetSessionOptionsRequest.Builder b = Flight.SetSessionOptionsRequest.newBuilder(); - // FIXME impl + b.putAllSessionOptions(sessionOptions.entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, (e) -> e.getValue().toProtocol()))); return b.build(); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java index 4c65c7ba1428e..f9fae134d3b79 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -21,6 +21,7 @@ import java.nio.ByteBuffer; import java.util.Collections; import java.util.Map; +import java.util.stream.Collectors; public class SetSessionOptionsResult { public enum Status { @@ -29,47 +30,73 @@ public enum Status { * (send a NOT_FOUND error if the requested session is not known). Clients can retry * the request. */ - UNSPECIFIED, + UNSPECIFIED(Flight.SetSessionOptionsResult.Status.UNSPECIFIED), /** * The session option setting completed successfully. */ - OK, + OK(Flight.SetSessionOptionsResult.Status.OK), /** * The given session option name was an alias for another option name. */ - OK_MAPPED, + OK_MAPPED(Flight.SetSessionOptionsResult.Status.OK_MAPPED), /** * The given session option name is invalid. */ - INVALID_NAME, + INVALID_NAME(Flight.SetSessionOptionsResult.Status.INVALID_NAME), /** * The session option value is invalid. */ - INVALID_VALUE, + INVALID_VALUE(Flight.SetSessionOptionsResult.Status.INVALID_VALUE), /** * The session option cannot be set. */ - ERROR, + ERROR(Flight.SetSessionOptionsResult.Status.ERROR), ; + + private static final Map mapFromProto; + + static { + for (Status s : values()) mapFromProto.put(s.proto, s); + } + + private final Flight.SetSessionOptionsResult.Status proto; + + private Status(Flight.SetSessionOptionsResult.Status s) { + proto = s; + } + + public static Status fromProtocol(Flight.SetSessionOptionsResult.Status s) { + return mapFromProto.get(s); + } + + public Flight.SetSessionOptionsResult.Status toProtocol() { + return proto; + } } private final Map results; public SetSessionOptionsResult(Map results) { - this.results = HashMap(results); + this.results = Collections.unmodifiableMap(new HashMap(results)); } SetSessionOptionsResult(Flight.SetSessionOptionsResult proto) { - // PHOXME impl + results = Collections.unmodifiableMap(proto.getResults().entrySet().stream().collect( + Collectors.toMap(Map.Entry::getKey, (e) -> Status.fromProtocol(e.getValue())))); } + /** + * + * @return An immutable view of the result status map. + */ Map getResults() { - return Collections.unmodifiableMap(results); + return results; } Flight.SetSessionOptionsResult toProtocol() { Flight.SetSessionOptionsResult.Builder b = Flight.SetSessionOptionsResult.newBuilder(); - // PHOXME impl + b.putAllResults(results.entrySet().stream().collect( + Collectors.toMap(Map.Entry::getKey, e -> getValue().toProtocol()))); return b.build(); } @@ -94,5 +121,4 @@ public ByteBuffer serialize() { public static SetSessionOptionsResult deserialize(ByteBuffer serialized) throws IOException { return new SetSessionOptionsResult(Flight.SetSessionOptionsResult.parseFrom(serialized)); } - } From b7881193b7f75f58f14fd42a3fc1b8617481013f Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 6 Dec 2023 14:26:38 -0800 Subject: [PATCH 108/195] Fixup --- .../java/org/apache/arrow/flight/SessionOptionValueFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 08d7720fdcd16..828e2e8233ff3 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -27,7 +27,7 @@ public static SessionOptionValue makeSessionOptionValue(String value) { } public static SessionOptionValue makeSessionOptionValue(bool value) { - return new SessionOptionValueBool(value); + return new SessionOptionValueBoolean(value); } public static SessionOptionValue makeSessionOptionValue(int value) { From c152ec2aea4e994ca50dac73a5add5daa15d0cd3 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 8 Dec 2023 13:06:32 -0800 Subject: [PATCH 109/195] Change SetSessionOptionResult (Proto) to error-only behaviour --- format/Flight.proto | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/format/Flight.proto b/format/Flight.proto index f4b0042020dcb..303209abfd5d1 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -558,30 +558,28 @@ message SetSessionOptionsRequest { /* * EXPERIMENTAL: The results (individually) of setting a set of session options. + * + * Option names should only be present in the */ message SetSessionOptionsResult { - enum Status { + enum ErrorValue { // The status of setting the option is unknown. Servers should avoid using // this value (send a NOT_FOUND error if the requested query is // not known). Clients can retry the request. UNSPECIFIED = 0; - // The session option setting completed successfully. - OK = 1; - // The given session option name was an alias for another option name. - OK_MAPPED = 2; // The given session option name is invalid. - INVALID_NAME = 3; + INVALID_NAME = 1; // The session option value is invalid. - INVALID_VALUE = 4; + INVALID_VALUE = 2; // The session option cannot be set. - ERROR = 5; + ERROR = 3; } - message Result { - Status status = 1; + message Error { + ErrorValue value = 1; } - map results = 1; + map errors = 1; } /* From 2f174f0a43c62f23626dd0489ea37a56c413482c Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 8 Dec 2023 13:14:54 -0800 Subject: [PATCH 110/195] [builds] Update C++ to error-only SetSessionOptionsResult --- .../arrow/flight/serialization_internal.cc | 14 ++++++------ cpp/src/arrow/flight/types.cc | 18 +++++++-------- cpp/src/arrow/flight/types.h | 22 ++++++++----------- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 4548e824ef53f..faac1e4092463 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -477,19 +477,19 @@ Status ToProto(const SetSessionOptionsRequest& request, Status FromProto(const pb::SetSessionOptionsResult& pb_result, SetSessionOptionsResult* result) { - for (const auto& [k, pb_v] : pb_result.results()) { - result->results.insert({k, {static_cast(pb_v.status())}}); + for (const auto& [k, pb_v] : pb_result.errors()) { + result->errors.insert({k, {static_cast(pb_v.value())}}); } return Status::OK(); } Status ToProto(const SetSessionOptionsResult& result, pb::SetSessionOptionsResult* pb_result) { - auto* pb_statuses = pb_result->mutable_results(); - for (const auto& [k, v] : result.results) { - pb::SetSessionOptionsResult::Result r; - r.set_status(static_cast(v.status)); - (*pb_statuses)[k] = std::move(r); + auto* pb_errors = pb_result->mutable_errors(); + for (const auto& [k, v] : result.errors) { + pb::SetSessionOptionsResult::Error e; + e.set_value(static_cast(v.value)); + (*pb_errors)[k] = std::move(e); } return Status::OK(); } diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index feb9f1a11eb65..ef8f7e496b2a7 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -476,17 +476,17 @@ arrow::Result CancelFlightInfoRequest::Deserialize( } static const char* const SetSessionOptionStatusNames[] = { - "Unspecified", "Ok", "OkMapped", "InvalidName", "InvalidValue", "Error"}; + "Unspecified", "InvalidName", "InvalidValue", "Error"}; static const char* const CloseSessionStatusNames[] = {"Unspecified", "Closed", "Closing", "NotClosable"}; // Helpers for stringifying maps containing various types -std::string ToString(const SetSessionOptionStatus& status) { - return SetSessionOptionStatusNames[static_cast(status)]; +std::string ToString(const SetSessionOptionErrorValue& error_value) { + return SetSessionOptionStatusNames[static_cast(error_value)]; } -std::ostream& operator<<(std::ostream& os, const SetSessionOptionStatus& status) { - os << ToString(status); +std::ostream& operator<<(std::ostream& os, const SetSessionOptionErrorValue& error_value) { + os << ToString(error_value); return os; } @@ -516,8 +516,8 @@ std::ostream& operator<<(std::ostream& os, const SessionOptionValue& v) { return os; } -std::ostream& operator<<(std::ostream& os, const SetSessionOptionsResult::Result& r) { - os << '{' << r.status << '}'; +std::ostream& operator<<(std::ostream& os, const SetSessionOptionsResult::Error& e) { + os << '{' << e.value << '}'; return os; } @@ -613,13 +613,13 @@ arrow::Result SetSessionOptionsRequest::Deserialize( std::string SetSessionOptionsResult::ToString() const { std::stringstream ss; - ss << " { + }); + return result; + } + + /** + * Request the server to extend the lifetime of a query result set. + * + * @param request The (empty) GetSessionOptionsRequest. + * @param options Call options. + * @return The result containing the set of session options configured on the server. + */ + public GetSessionOptionsResult getSessionOptions(SetSessionOptionsRequest request, CallOption... options) { + Action action = new Action(FlightConstants.GET_SESSION_OPTIONS.getType(), request.serialize().array()); + Iterator results = doAction(action, options); + if (!results.hasNext()) { + throw CallStatus.INTERNAL + .withDescription("Server did not return a response") + .toRuntimeException(); + } + + FlightGetSessionOptionsResultEndpoint result; + try { + result = GetSessionOptionsResult.deserialize(ByteBuffer.wrap(results.next().getBody())); + } catch (IOException e) { + throw CallStatus.INTERNAL + .withDescription("Failed to parse server response: " + e) + .withCause(e) + .toRuntimeException(); + } + results.forEachRemaining((ignored) -> { + }); + return result; + } + + /** + * Request the server to extend the lifetime of a query result set. + * + * @param request The (empty) CloseSessionRequest. + * @param options Call options. + * @return The result containing the status of the close operation. + */ + public CloseSessionResult closeSession(SetSessionOptionsRequest request, CallOption... options) { + Action action = new Action(FlightConstants.CLOSE_SESSION.getType(), request.serialize().array()); + Iterator results = doAction(action, options); + if (!results.hasNext()) { + throw CallStatus.INTERNAL + .withDescription("Server did not return a response") + .toRuntimeException(); + } + + CloseSessionResult result; + try { + result = CloseSessionResult.deserialize(ByteBuffer.wrap(results.next().getBody())); + } catch (IOException e) { + throw CallStatus.INTERNAL + .withDescription("Failed to parse server response: " + e) + .withCause(e) + .toRuntimeException(); + } + results.forEachRemaining((ignored) -> { + }); + return result; + } +//////////////////////////////////////////////// + /** * Interface for writers to an Arrow data stream. */ diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java index a98ec8ce4b379..bc11d7de046f8 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.nio.ByteBuffer; +import org.apache.arrow.flight.impl.Flight; + public class GetSessionOptionsRequest { public GetSessionOptionsRequest() {} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java index 0df5053c92750..6090c5b219d1f 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java @@ -23,6 +23,9 @@ import java.util.Map; import java.util.stream.Collectors; +import org.apache.arrow.flight.impl.Flight; + +/** A request to view the currently-set options for the current server session. */ public class GetSessionOptionsResult { private final Map sessionOptions; diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index 8ff85af6788cf..f311b0f0e8f7c 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -28,7 +28,7 @@ public abstract class SessionOptionValue { /** * Value access via a caller-provided visitor/functor. */ - abstract void acceptVisitor(SessionOptionValueVisitor); + abstract acceptVisitor(SessionOptionValueVisitor); Flight.SessionOptionValue toProtocol() { Flight.SessionOptionValue.Builder b = Flight.SessionOptionValue.newBuilder(); @@ -38,36 +38,45 @@ Flight.SessionOptionValue toProtocol() { } } -class SessionOptionValueToProtocolVisitor implements SessionOptionValueVisitor { +class SessionOptionValueToProtocolVisitor implements SessionOptionValueVisitor { final Flight.SessionOptionValue.Builder b; SessionOptionValueVisitor(Flight.SessionOptionValue.Builder b) { this.b = b; } - void visit(String value) { + Void visit(String value) { b.setStringValue(value); + return null; } - void visit(boolean value) { b.setBoolValue(value); } + Void visit(boolean value) { + b.setBoolValue(value); + return null; + } - void visit(int value) { + Void visit(int value) { b.setIn32Value(value); + return null; } - void visit(long value) { + Void visit(long value) { b.setInt64Value(value); + return null; } - void visit(float value) { + Void visit(float value) { b.setFloatValue(value); + return null; } - void visit(double value) { + Void visit(double value) { b.setDoubleValue(value); + return null; } - void visit(String[] value) { + Void visit(String[] value) { Flight.SessionOptionValue.StringListValue pbValue; pbValue.addAllStringValues(value); b.setValue(pbValue); + return null; } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 828e2e8233ff3..ced37c8dd40c7 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -19,8 +19,9 @@ import java.util.stream.Collectors; -import org.apache.arrow.flight.SessionOptionValue; +import com.google.protobuf; +/** Abstract factory for concrete SessionOptionValue instances. */ public class SessionOptionValueFactory { public static SessionOptionValue makeSessionOptionValue(String value) { return new SessionOptionValueString(value); diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java index f502e78fb5635..68d1d91ee0891 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java @@ -20,39 +20,39 @@ /** * A visitor interface to access SessionOptionValue's contained value. */ -public interface SessionOptionValueVisitor { +public interface SessionOptionValueVisitor { /** * A callback to handle SessionOptionValue containing a String. */ - void visit(String value); + T visit(String value); /** * A callback to handle SessionOptionValue containing a boolean. */ - void visit(boolean value); + T visit(boolean value); /** * A callback to handle SessionOptionValue containing an int. */ - void visit(int value); + T visit(int value); /** * A callback to handle SessionOptionValue containing a long. */ - void visit(long value); + T visit(long value); /** * A callback to handle SessionOptionValue containing a float. */ - void visit(float value); + T visit(float value); /** * A callback to handle SessionOptionValue containing a double. */ - void visit(double value); + T visit(double value); /** * A callback to handle SessionOptionValue containing an array of String. */ - void visit(String[] value); + T visit(String[] value); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java index 5839d9fa044e0..7af4298ca5852 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java @@ -23,6 +23,9 @@ import java.util.Map; import java.util.stream.Collectors; +import org.apache.arrow.flight.impl.Flight; + +/** A request to set option(s) in an existing or implicitly-created server session. */ public class SetSessionOptionsRequest { private final Map sessionOptions; diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java index f9fae134d3b79..0ddb1dfabdaee 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -23,80 +23,85 @@ import java.util.Map; import java.util.stream.Collectors; +import org.apache.arrow.flight.impl.Flight; + +/** The result of attempting to set a set of session options. */ public class SetSessionOptionsResult { - public enum Status { + public enum ErrorValue { /** * The status of setting the option is unknown. Servers should avoid using this value * (send a NOT_FOUND error if the requested session is not known). Clients can retry * the request. */ - UNSPECIFIED(Flight.SetSessionOptionsResult.Status.UNSPECIFIED), - /** - * The session option setting completed successfully. - */ - OK(Flight.SetSessionOptionsResult.Status.OK), - /** - * The given session option name was an alias for another option name. - */ - OK_MAPPED(Flight.SetSessionOptionsResult.Status.OK_MAPPED), + UNSPECIFIED(Flight.SetSessionOptionsResult.ErrorValue.UNSPECIFIED), /** * The given session option name is invalid. */ - INVALID_NAME(Flight.SetSessionOptionsResult.Status.INVALID_NAME), + INVALID_NAME(Flight.SetSessionOptionsResult.ErrorValue.INVALID_NAME), /** * The session option value is invalid. */ - INVALID_VALUE(Flight.SetSessionOptionsResult.Status.INVALID_VALUE), + INVALID_VALUE(Flight.SetSessionOptionsResult.ErrorValue.INVALID_VALUE), /** * The session option cannot be set. */ - ERROR(Flight.SetSessionOptionsResult.Status.ERROR), + ERROR(Flight.SetSessionOptionsResult.ErrorValue.ERROR), ; - private static final Map mapFromProto; - - static { - for (Status s : values()) mapFromProto.put(s.proto, s); + static ErrorValue fromProtocol(Flight.SetSessionOptionsResult.ErrorValue s) { + return values()[s.ordinal()]; } - private final Flight.SetSessionOptionsResult.Status proto; - - private Status(Flight.SetSessionOptionsResult.Status s) { - proto = s; + Flight.SetSessionOptionsResult.Status toProtocol() { + return return Flight.SetSessionOptionsResult.ErrorValue.values()[ordinal()]; } + } + + public class Error { + public ErrorValue value; - public static Status fromProtocol(Flight.SetSessionOptionsResult.Status s) { - return mapFromProto.get(s); + static Error fromProtocol(Flight.SetSessionOptionsResult.Error e) { + return Error(ErrorValue.fromProtocol(e.getValue())); } - public Flight.SetSessionOptionsResult.Status toProtocol() { - return proto; + Flight.SetSessionOptionsResult.Error toProtocol() { + Flight.SetSessionOptionsResult.Error b = Flight.SetSessionOptionsResult.newBuilder(); + b.setValue(value.toProtocol()); + return b.build(); } } - private final Map results; + private final Map errors; - public SetSessionOptionsResult(Map results) { - this.results = Collections.unmodifiableMap(new HashMap(results)); + public SetSessionOptionsResult(Map errors) { + this.errors = Collections.unmodifiableMap(new HashMap(errors)); } SetSessionOptionsResult(Flight.SetSessionOptionsResult proto) { - results = Collections.unmodifiableMap(proto.getResults().entrySet().stream().collect( - Collectors.toMap(Map.Entry::getKey, (e) -> Status.fromProtocol(e.getValue())))); + errors = Collections.unmodifiableMap(proto.getErrors().entrySet().stream().collect( + Collectors.toMap(Map.Entry::getKey, (e) -> Error.fromProtocol(e.getValue())))); + } + + public boolean hasErrors() { + return errors.size() > 0; } /** * - * @return An immutable view of the result status map. + * @return An immutable view of the error status map. */ - Map getResults() { - return results; + public Map getErrors() { + return errors; } Flight.SetSessionOptionsResult toProtocol() { Flight.SetSessionOptionsResult.Builder b = Flight.SetSessionOptionsResult.newBuilder(); - b.putAllResults(results.entrySet().stream().collect( - Collectors.toMap(Map.Entry::getKey, e -> getValue().toProtocol()))); + b.putAllResults(errors.entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, + (e) -> { + Flight.SetSessionOptionsResult.Error.builder b = Flight.SetSessionOptionsResult.Error.newBuilder(); + b.setValue(Error.fromProtocol(e.getValue())); + return b.build(); } ))); return b.build(); } diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java new file mode 100644 index 0000000000000..fd2b7838c15c0 --- /dev/null +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java @@ -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. + */ + +package org.apache.arrow.flight.sql; + +import org.apache.arrow.flight.CloseSessionResult; +import org.apache.arrow.flight.FlightProducer; +import org.apache.arrow.flight.Result; + +/** Typed StreamListener for renewFlightEndpoint. */ +public class FlightEndpointListener implements FlightProducer.StreamListener { + private final FlightProducer.StreamListener listener; + + FlightEndpointListener(FlightProducer.StreamListener listener) { + this.listener = listener; + } + + @Override + public void onNext(CloseSessionResult val) { + listener.onNext(new Result(val.serialize().array())); + } + + @Override + public void onError(Throwable t) { + listener.onError(t); + } + + @Override + public void onCompleted() { + listener.onCompleted(); + } +} diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlClient.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlClient.java index 93d933f00f38f..c2a82b149fe2c 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlClient.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlClient.java @@ -61,15 +61,21 @@ import org.apache.arrow.flight.CallStatus; import org.apache.arrow.flight.CancelFlightInfoRequest; import org.apache.arrow.flight.CancelFlightInfoResult; +import org.apache.arrow.flight.CloseSessionRequest; +import org.apache.arrow.flight.CloseSessionResult; import org.apache.arrow.flight.FlightClient; import org.apache.arrow.flight.FlightDescriptor; import org.apache.arrow.flight.FlightEndpoint; import org.apache.arrow.flight.FlightInfo; import org.apache.arrow.flight.FlightStream; +import org.apache.arrow.flight.GetSessionOptionsRequest; +import org.apache.arrow.flight.GetSessionOptionsResult; import org.apache.arrow.flight.PutResult; import org.apache.arrow.flight.RenewFlightEndpointRequest; import org.apache.arrow.flight.Result; import org.apache.arrow.flight.SchemaResult; +import org.apache.arrow.flight.SetSessionOptionsRequest; +import org.apache.arrow.flight.SetSessionOptionsResult; import org.apache.arrow.flight.SyncPutListener; import org.apache.arrow.flight.Ticket; import org.apache.arrow.flight.sql.impl.FlightSql.ActionCreatePreparedStatementResult; @@ -917,6 +923,18 @@ public FlightEndpoint renewFlightEndpoint(RenewFlightEndpointRequest request, Ca return client.renewFlightEndpoint(request, options); } + public SetSessionOptionsResult setSessionOptions(SetSessionOptionsRequest request, CallOption... options) { + return client.cancelFlightInfo(request, options); + } + + public GetSessionOptionsResult getSessionOptions(GetSessionOptionsRequest request, CallOption... options) { + return client.cancelFlightInfo(request, options); + } + + public CloseSessionResult closeSession(CloseSessionRequest request, CallOption... options) { + return client.cancelFlightInfo(request, options); + } + @Override public void close() throws Exception { AutoCloseables.close(client); diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java index 4230903b25dd4..0d6ee782fd70f 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java @@ -57,6 +57,7 @@ import org.apache.arrow.flight.CancelFlightInfoRequest; import org.apache.arrow.flight.CancelStatus; import org.apache.arrow.flight.CloseSessionRequest; +import org.apache.arrow.flight.CloseSessionResult; import org.apache.arrow.flight.FlightConstants; import org.apache.arrow.flight.FlightDescriptor; import org.apache.arrow.flight.FlightEndpoint; @@ -64,11 +65,13 @@ import org.apache.arrow.flight.FlightProducer; import org.apache.arrow.flight.FlightStream; import org.apache.arrow.flight.GetSessionOptionsRequest; +import org.apache.arrow.flight.GetSessionOptionsResult; import org.apache.arrow.flight.PutResult; import org.apache.arrow.flight.RenewFlightEndpointRequest; import org.apache.arrow.flight.Result; import org.apache.arrow.flight.SchemaResult; import org.apache.arrow.flight.SetSessionOptionsRequest; +import org.apache.arrow.flight.SetSessionOptionsResult; import org.apache.arrow.flight.Ticket; import org.apache.arrow.flight.sql.impl.FlightSql.ActionClosePreparedStatementRequest; import org.apache.arrow.flight.sql.impl.FlightSql.ActionCreatePreparedStatementRequest; @@ -386,6 +389,42 @@ default void doAction(CallContext context, Action action, StreamListener return; } renewFlightEndpoint(request, context, new FlightEndpointListener(listener)); + } else if (actionType.equals(FlightConstants.SET_SESSION_OPTIONS.getType())) { + final SetSessionOptionsRequest request; + try { + request = SetSessionOptionsRequest.deserialize(ByteBuffer.wrap(action.getBody())); + } catch (IOException e) { + listener.onError(CallStatus.INTERNAL + .withDescription("Could not unpack SetSessionOptionsRequest: " + e) + .withCause(e) + .toRuntimeException()); + return; + } + setSessionOptions(request, context, new SetSessionOptionsResultListener(listener)); + } else if (actionType.equals(FlightConstants.GET_SESSION_OPTIONS.getType())) { + final GetSessionOptionsRequest request; + try { + request = GetSessionOptionsRequest.deserialize(ByteBuffer.wrap(action.getBody())); + } catch (IOException e) { + listener.onError(CallStatus.INTERNAL + .withDescription("Could not unpack GetSessionOptionsRequest: " + e) + .withCause(e) + .toRuntimeException()); + return; + } + getSessionOptions(request, context, new GetSessionOptionsResultListener(listener)); + } else if (actionType.equals(FlightConstants.CLOSE_SESSION.getType())) { + final CloseSessionRequest request; + try { + request = CloseSessionRequest.deserialize(ByteBuffer.wrap(action.getBody())); + } catch (IOException e) { + listener.onError(CallStatus.INTERNAL + .withDescription("Could not unpack CloseSessionRequest: " + e) + .withCause(e) + .toRuntimeException()); + return; + } + closeSession(request, context, new CloseSessionResultListener(listener)); } else { throw CallStatus.INVALID_ARGUMENT .withDescription("Unrecognized request: " + action.getType()) @@ -475,6 +514,42 @@ public void onCompleted() { }); } + /** + * Set server session options(s). + * + * @param request The SetSessionOptionsRequest to set options from. + * @param context Per-call context. + * @param listener An interface for sending data back to the client. + */ + default void setSessionOptions(SetSessionOptionsRequest request, CallContext context, + StreamListener listener) { + listener.onError(CallStatus.UNIMPLEMENTED.toRuntimeException()); + } + + /** + * Get server session option(s). + * + * @param request The (empty) GetSessionOptionsRequest. + * @param context Per-call context. + * @param listener An interface for sending data back to the client. + */ + default void getSessionOptions(GetSessionOptionsRequest request, CallContext context, + StreamListener listener) { + listener.onError(CallStatus.UNIMPLEMENTED.toRuntimeException()); + } + + /** + * Close/invalidate the session. + * + * @param request The (empty) CloseSessionRequest. + * @param context Per-call context. + * @param listener An interface for sending data back to the client. + */ + default void closeSession(CloseSessionRequest request, CallContext context, + StreamListener listener) { + listener.onError(CallStatus.UNIMPLEMENTED.toRuntimeException()); + } + /** * Creates a prepared statement on the server and returns a handle and metadata for in a * {@link ActionCreatePreparedStatementResult} object in a {@link Result} diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java new file mode 100644 index 0000000000000..df3b65ec59c06 --- /dev/null +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java @@ -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. + */ + +package org.apache.arrow.flight.sql; + +import org.apache.arrow.flight.FlightProducer; +import org.apache.arrow.flight.GetSessionOptionsResult; +import org.apache.arrow.flight.Result; + +/** Typed StreamListener for renewFlightEndpoint. */ +public class FlightEndpointListener implements FlightProducer.StreamListener { + private final FlightProducer.StreamListener listener; + + FlightEndpointListener(FlightProducer.StreamListener listener) { + this.listener = listener; + } + + @Override + public void onNext(GetSessionOptionsResult val) { + listener.onNext(new Result(val.serialize().array())); + } + + @Override + public void onError(Throwable t) { + listener.onError(t); + } + + @Override + public void onCompleted() { + listener.onCompleted(); + } +} diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java new file mode 100644 index 0000000000000..7992bfc432c4b --- /dev/null +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java @@ -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. + */ + +package org.apache.arrow.flight.sql; + +import org.apache.arrow.flight.FlightProducer; +import org.apache.arrow.flight.Result; +import org.apache.arrow.flight.SetSessionOptionsResult; + +/** Typed StreamListener for renewFlightEndpoint. */ +public class FlightEndpointListener implements FlightProducer.StreamListener { + private final FlightProducer.StreamListener listener; + + FlightEndpointListener(FlightProducer.StreamListener listener) { + this.listener = listener; + } + + @Override + public void onNext(SetSessionOptionsResult val) { + listener.onNext(new Result(val.serialize().array())); + } + + @Override + public void onError(Throwable t) { + listener.onError(t); + } + + @Override + public void onCompleted() { + listener.onCompleted(); + } +} From 31ceb718ba14b024cb703649eda8274a24858e74 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 8 Dec 2023 22:58:26 -0800 Subject: [PATCH 112/195] Fix some checkstyle errors --- .../arrow/flight/CloseSessionResult.java | 6 +- .../org/apache/arrow/flight/FlightClient.java | 2 - .../apache/arrow/flight/FlightConstants.java | 12 +- .../arrow/flight/GetSessionOptionsResult.java | 2 +- .../arrow/flight/SessionOptionValue.java | 86 ++++---- .../flight/SessionOptionValueFactory.java | 184 +++++++++--------- .../flight/SessionOptionValueVisitor.java | 68 +++---- .../flight/SetSessionOptionsRequest.java | 10 +- .../arrow/flight/SetSessionOptionsResult.java | 2 +- 9 files changed, 183 insertions(+), 189 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java index c98081600d4b8..b3b5bcc93b63c 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java @@ -63,8 +63,8 @@ public CloseSessionResult(Status status) { CloseSessionResult(Flight.CloseSessionResult proto) { status = Status.fromProtocol(proto.getStatus()); if (status == null) { - // Unreachable - throw new IllegalArgumentException(""); + // Unreachable + throw new IllegalArgumentException(""); } } @@ -74,7 +74,7 @@ Status getStatus() { Flight.CloseSessionResult toProtocol() { Flight.CloseSessionResult.Builder b = Flight.CloseSessionResult.newBuilder(); - b.setStatus(status.toProtocol()): + b.setStatus(status.toProtocol()); return b.build(); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java index bdd1e7ffe2302..c96b12dc3f12e 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java @@ -580,7 +580,6 @@ public FlightEndpoint renewFlightEndpoint(RenewFlightEndpointRequest request, Ca return result; } -//////////////////////////////////////////////// /** * Request the server to extend the lifetime of a query result set. * @@ -670,7 +669,6 @@ public CloseSessionResult closeSession(SetSessionOptionsRequest request, CallOpt }); return result; } -//////////////////////////////////////////////// /** * Interface for writers to an Arrow data stream. diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightConstants.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightConstants.java index 0386bae4bf9a0..4456e3dae4949 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightConstants.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightConstants.java @@ -37,16 +37,16 @@ public interface FlightConstants { "Response Message: Renewed FlightEndpoint"); ActionType SET_SESSION_OPTIONS = new ActionType("SetSessionOptions", - "Set client session options by name/value pairs.\n" - "Request Message: SetSessionOptionsRequest\n" + "Set client session options by name/value pairs.\n" + + "Request Message: SetSessionOptionsRequest\n" + "Response Message: SetSessionOptionsResult"); ActionType GET_SESSION_OPTIONS = new ActionType("GetSessionOptions", - "Get current client session options\n" - "Request Message: GetSessionOptionsRequest\n" + "Get current client session options\n" + + "Request Message: GetSessionOptionsRequest\n" + "Response Message: GetSessionOptionsResult"); ActionType CLOSE_SESSION = new ActionType("CloseSession", - "Explicitly close/invalidate the cookie-specified client session.\n" - "Request Message: CloseSessionRequest\n" + "Explicitly close/invalidate the cookie-specified client session.\n" + + "Request Message: CloseSessionRequest\n" + "Response Message: CloseSessionResult"); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java index 6090c5b219d1f..2ab26a438ab4a 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java @@ -44,7 +44,7 @@ public GetSessionOptionsResult(Map sessionOptions) { * @return An immutable view of the session options map. */ public Map getSessionOptions() { - return new sessionOptions; + return sessionOptions; } Flight.GetSessionOptionsResult toProtocol() { diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index f311b0f0e8f7c..7c7f01fa19470 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -17,66 +17,64 @@ package org.apache.arrow.flight; -import java.util.stream.Collectors; - import org.apache.arrow.flight.impl.Flight; /** * A union-like container interface for supported session option value types. */ public abstract class SessionOptionValue { - /** - * Value access via a caller-provided visitor/functor. - */ - abstract acceptVisitor(SessionOptionValueVisitor); + /** + * Value access via a caller-provided visitor/functor. + */ + abstract T acceptVisitor(SessionOptionValueVisitor v); - Flight.SessionOptionValue toProtocol() { - Flight.SessionOptionValue.Builder b = Flight.SessionOptionValue.newBuilder(); - SessionOptionValueToProtocolVisitor visitor = new SessionOptionValueToProtocolVisitor(b); - this.acceptVisitor(visitor); - return b.build(); - } + Flight.SessionOptionValue toProtocol() { + Flight.SessionOptionValue.Builder b = Flight.SessionOptionValue.newBuilder(); + SessionOptionValueToProtocolVisitor visitor = new SessionOptionValueToProtocolVisitor(b); + this.acceptVisitor(visitor); + return b.build(); + } } class SessionOptionValueToProtocolVisitor implements SessionOptionValueVisitor { - final Flight.SessionOptionValue.Builder b; + final Flight.SessionOptionValue.Builder b; - SessionOptionValueVisitor(Flight.SessionOptionValue.Builder b) { this.b = b; } + SessionOptionValueVisitor(Flight.SessionOptionValue.Builder b) { this.b = b; } - Void visit(String value) { - b.setStringValue(value); - return null; - } + Void visit(String value) { + b.setStringValue(value); + return null; + } - Void visit(boolean value) { - b.setBoolValue(value); - return null; - } + Void visit(boolean value) { + b.setBoolValue(value); + return null; + } - Void visit(int value) { - b.setIn32Value(value); - return null; - } + Void visit(int value) { + b.setIn32Value(value); + return null; + } - Void visit(long value) { - b.setInt64Value(value); - return null; - } + Void visit(long value) { + b.setInt64Value(value); + return null; + } - Void visit(float value) { - b.setFloatValue(value); - return null; - } + Void visit(float value) { + b.setFloatValue(value); + return null; + } - Void visit(double value) { - b.setDoubleValue(value); - return null; - } + Void visit(double value) { + b.setDoubleValue(value); + return null; + } - Void visit(String[] value) { - Flight.SessionOptionValue.StringListValue pbValue; - pbValue.addAllStringValues(value); - b.setValue(pbValue); - return null; - } + Void visit(String[] value) { + Flight.SessionOptionValue.StringListValue pbValue; + pbValue.addAllStringValues(value); + b.setValue(pbValue); + return null; + } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index ced37c8dd40c7..9d4bb2277450f 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -19,143 +19,141 @@ import java.util.stream.Collectors; -import com.google.protobuf; - /** Abstract factory for concrete SessionOptionValue instances. */ public class SessionOptionValueFactory { - public static SessionOptionValue makeSessionOptionValue(String value) { - return new SessionOptionValueString(value); - } - - public static SessionOptionValue makeSessionOptionValue(bool value) { - return new SessionOptionValueBoolean(value); - } - - public static SessionOptionValue makeSessionOptionValue(int value) { - return new SessionOptionValueInt(value); - } - - public static SessionOptionValue makeSessionOptionValue(long value) { - return new SessionOptionValueLong(value); - } - - public static SessionOptionValue makeSessionOptionValue(float value) { - return new SessionOptionValueFloat(value); - } - - public static SessionOptionValue makeSessionOptionValue(double value) { - return new SessionOptionValueDouble(value); - } - - public static SessionOptionValue makeSessionOptionValue(String[] value) { - return new SessionOptionValueStringList(value); - } - - public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValue proto) { - switch(proto.getOptionValueCase()) { - case STRING_VALUE: - return new SessionOptionValueString(proto.getStringValue()); - case BOOL_VALUE: - return new SessionOptionValueBoolean(proto.getValue()); - case INT32_VALUE: - return new SessionOptionValueInteger(proto.getInt32Value()); - case INT64_VALUE: - return new SessionOptionValueLong(proto.getInt64Value()); - case FLOAT_VALUE: - return new SessionOptionValueFloat(proto.getFloatValue()); - case DOUBLE_VALUE: - return new SessionOptionValueDouble(proto.getDoubleValue()); - case STRING_LIST_VALUE: - // FIXME PHOXME is this what's in the ProtocolStringList? - return new SessionOptionValueStringList(proto.getValueStringList().stream().collect( - Collectors.toList(e -> google.protocol.StringValue.parseFrom(e).getValue()))); - default: - // Unreachable - throw new IllegalArgumentException(""); - } - } + public static SessionOptionValue makeSessionOptionValue(String value) { + return new SessionOptionValueString(value); + } + + public static SessionOptionValue makeSessionOptionValue(bool value) { + return new SessionOptionValueBoolean(value); + } + + public static SessionOptionValue makeSessionOptionValue(int value) { + return new SessionOptionValueInt(value); + } + + public static SessionOptionValue makeSessionOptionValue(long value) { + return new SessionOptionValueLong(value); + } + + public static SessionOptionValue makeSessionOptionValue(float value) { + return new SessionOptionValueFloat(value); + } + + public static SessionOptionValue makeSessionOptionValue(double value) { + return new SessionOptionValueDouble(value); + } + + public static SessionOptionValue makeSessionOptionValue(String[] value) { + return new SessionOptionValueStringList(value); + } + + public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValue proto) { + switch(proto.getOptionValueCase()) { + case STRING_VALUE: + return new SessionOptionValueString(proto.getStringValue()); + case BOOL_VALUE: + return new SessionOptionValueBoolean(proto.getValue()); + case INT32_VALUE: + return new SessionOptionValueInteger(proto.getInt32Value()); + case INT64_VALUE: + return new SessionOptionValueLong(proto.getInt64Value()); + case FLOAT_VALUE: + return new SessionOptionValueFloat(proto.getFloatValue()); + case DOUBLE_VALUE: + return new SessionOptionValueDouble(proto.getDoubleValue()); + case STRING_LIST_VALUE: + // FIXME PHOXME is this what's in the ProtocolStringList? + return new SessionOptionValueStringList(proto.getValueStringList().stream().collect( + Collectors.toList(e -> google.protocol.StringValue.parseFrom(e).getValue()))); + default: + // Unreachable + throw new IllegalArgumentException(""); + } + } } class SessionOptionValueString extends SessionOptionvalue { - private final String value; + private final String value; - SessionOptionValue(String value) { - this.value = value; - } + SessionOptionValue(String value) { + this.value = value; + } - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); - } + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } class SessionOptionValueBoolean extends SessionOptionvalue { - private final boolean value; + private final boolean value; - SessionOptionValueBoolean(boolean value) { - this.value = value; - } + SessionOptionValueBoolean(boolean value) { + this.value = value; + } - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); - } + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } class SessionOptionValueInt extends SessionOptionvalue { - private final int value; + private final int value; - SessionOptionValueInt(int value) { - this.value = value; - } + SessionOptionValueInt(int value) { + this.value = value; + } - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); - } + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } class SessionOptionValueLong extends SessionOptionvalue { - private final long value; + private final long value; - SessionOptionValueLong(long value) { + SessionOptionValueLong(long value) { this.value = value; - } + } - void acceptVisitor(SessionOptionValueVisitor v) { + void acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); - } + } } class SessionOptionValueFloat extends SessionOptionvalue { - private final float value; + private final float value; - SessionOptionValueFloat(Float value) { + SessionOptionValueFloat(Float value) { this.value = value; - } + } - void acceptVisitor(SessionOptionValueVisitor v) { + void acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); - } + } } class SessionOptionValueDouble extends SessionOptionvalue { private final double value; - SessionOptionValueDouble(double value) { + SessionOptionValueDouble(double value) { this.value = value; - } + } - void acceptVisitor(SessionOptionValueVisitor v) { + void acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); - } + } } class SessionOptionValueStringList extends SessionOptionvalue { - private final String[] value; + private final String[] value; - SessionOptionValueStringList(String[] value) { + SessionOptionValueStringList(String[] value) { this.value = value.clone(); - } + } - void acceptVisitor(SessionOptionValueVisitor v) { + void acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); - } + } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java index 68d1d91ee0891..6fd65fdb65801 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java @@ -21,38 +21,38 @@ * A visitor interface to access SessionOptionValue's contained value. */ public interface SessionOptionValueVisitor { - /** - * A callback to handle SessionOptionValue containing a String. - */ - T visit(String value); - - /** - * A callback to handle SessionOptionValue containing a boolean. - */ - T visit(boolean value); - - /** - * A callback to handle SessionOptionValue containing an int. - */ - T visit(int value); - - /** - * A callback to handle SessionOptionValue containing a long. - */ - T visit(long value); - - /** - * A callback to handle SessionOptionValue containing a float. - */ - T visit(float value); - - /** - * A callback to handle SessionOptionValue containing a double. - */ - T visit(double value); - - /** - * A callback to handle SessionOptionValue containing an array of String. - */ - T visit(String[] value); + /** + * A callback to handle SessionOptionValue containing a String. + */ + T visit(String value); + + /** + * A callback to handle SessionOptionValue containing a boolean. + */ + T visit(boolean value); + + /** + * A callback to handle SessionOptionValue containing an int. + */ + T visit(int value); + + /** + * A callback to handle SessionOptionValue containing a long. + */ + T visit(long value); + + /** + * A callback to handle SessionOptionValue containing a float. + */ + T visit(float value); + + /** + * A callback to handle SessionOptionValue containing a double. + */ + T visit(double value); + + /** + * A callback to handle SessionOptionValue containing an array of String. + */ + T visit(String[] value); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java index 7af4298ca5852..01ec3188b9541 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java @@ -39,12 +39,12 @@ public SetSessionOptionsRequest(Map sessionOptions) Map.Entry::getKey, (e) -> SessionOptionValueFactory.makeSessionOptionValue(e.getValue())))); } - /** - * - * @return An immutable view of the session options map. - */ + /** + * + * @return An immutable view of the session options map. + */ public Map getSessionOptions() { - return new Collections.unmodifiableMap(sessionOptions); + return new Collections.unmodifiableMap(sessionOptions); } Flight.SetSessionOptionsRequest toProtocol() { diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java index 0ddb1dfabdaee..830bdda7e5dc9 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -53,7 +53,7 @@ static ErrorValue fromProtocol(Flight.SetSessionOptionsResult.ErrorValue s) { } Flight.SetSessionOptionsResult.Status toProtocol() { - return return Flight.SetSessionOptionsResult.ErrorValue.values()[ordinal()]; + return Flight.SetSessionOptionsResult.ErrorValue.values()[ordinal()]; } } From ebca8c26bf3eec840edbc616d1b54ece21ef28b9 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 8 Dec 2023 23:13:02 -0800 Subject: [PATCH 113/195] Fix some more checkstyle errors --- .../arrow/flight/CloseSessionResult.java | 3 + .../arrow/flight/GetSessionOptionsResult.java | 1 + .../arrow/flight/SessionOptionValue.java | 68 +++++----- .../flight/SessionOptionValueFactory.java | 116 +++++++++--------- .../flight/SessionOptionValueVisitor.java | 2 + 5 files changed, 99 insertions(+), 91 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java index b3b5bcc93b63c..7ddc767a32c8d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java @@ -24,6 +24,9 @@ /** The result of attempting to close/invalidate a server session context. */ public class CloseSessionResult { + /** + * Close operation result status values. + */ public enum Status { /** * The session close status is unknown. Servers should avoid using this value diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java index 2ab26a438ab4a..337bd75474a4d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java @@ -40,6 +40,7 @@ public GetSessionOptionsResult(Map sessionOptions) { } /** + * Get the session options map contained in the request. * * @return An immutable view of the session options map. */ diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index 7c7f01fa19470..e685a187ad84e 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -34,47 +34,49 @@ Flight.SessionOptionValue toProtocol() { this.acceptVisitor(visitor); return b.build(); } -} -class SessionOptionValueToProtocolVisitor implements SessionOptionValueVisitor { - final Flight.SessionOptionValue.Builder b; + private class SessionOptionValueToProtocolVisitor implements SessionOptionValueVisitor { + final Flight.SessionOptionValue.Builder b; - SessionOptionValueVisitor(Flight.SessionOptionValue.Builder b) { this.b = b; } + SessionOptionValueVisitor(Flight.SessionOptionValue.Builder b) { + this.b = b; + } - Void visit(String value) { - b.setStringValue(value); - return null; - } + Void visit(String value) { + b.setStringValue(value); + return null; + } - Void visit(boolean value) { - b.setBoolValue(value); - return null; - } + Void visit(boolean value) { + b.setBoolValue(value); + return null; + } - Void visit(int value) { - b.setIn32Value(value); - return null; - } + Void visit(int value) { + b.setIn32Value(value); + return null; + } - Void visit(long value) { - b.setInt64Value(value); - return null; - } + Void visit(long value) { + b.setInt64Value(value); + return null; + } - Void visit(float value) { - b.setFloatValue(value); - return null; - } + Void visit(float value) { + b.setFloatValue(value); + return null; + } - Void visit(double value) { - b.setDoubleValue(value); - return null; - } + Void visit(double value) { + b.setDoubleValue(value); + return null; + } - Void visit(String[] value) { - Flight.SessionOptionValue.StringListValue pbValue; - pbValue.addAllStringValues(value); - b.setValue(pbValue); - return null; + Void visit(String[] value) { + Flight.SessionOptionValue.StringListValue pbValue; + pbValue.addAllStringValues(value); + b.setValue(pbValue); + return null; + } } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 9d4bb2277450f..88f602c62870d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -42,7 +42,7 @@ public static SessionOptionValue makeSessionOptionValue(float value) { } public static SessionOptionValue makeSessionOptionValue(double value) { - return new SessionOptionValueDouble(value); + return new SessionOptionValueDouble(value); } public static SessionOptionValue makeSessionOptionValue(String[] value) { @@ -50,7 +50,7 @@ public static SessionOptionValue makeSessionOptionValue(String[] value) { } public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValue proto) { - switch(proto.getOptionValueCase()) { + switch (proto.getOptionValueCase()) { case STRING_VALUE: return new SessionOptionValueString(proto.getStringValue()); case BOOL_VALUE: @@ -72,88 +72,88 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu throw new IllegalArgumentException(""); } } -} -class SessionOptionValueString extends SessionOptionvalue { - private final String value; + class SessionOptionValueString extends SessionOptionvalue { + private final String value; - SessionOptionValue(String value) { - this.value = value; - } + SessionOptionValue(String value) { + this.value = value; + } - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -} -class SessionOptionValueBoolean extends SessionOptionvalue { - private final boolean value; + class SessionOptionValueBoolean extends SessionOptionvalue { + private final boolean value; - SessionOptionValueBoolean(boolean value) { - this.value = value; - } + SessionOptionValueBoolean(boolean value) { + this.value = value; + } - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -} -class SessionOptionValueInt extends SessionOptionvalue { - private final int value; + class SessionOptionValueInt extends SessionOptionvalue { + private final int value; - SessionOptionValueInt(int value) { - this.value = value; - } + SessionOptionValueInt(int value) { + this.value = value; + } - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -} -class SessionOptionValueLong extends SessionOptionvalue { - private final long value; + class SessionOptionValueLong extends SessionOptionvalue { + private final long value; - SessionOptionValueLong(long value) { - this.value = value; - } + SessionOptionValueLong(long value) { + this.value = value; + } - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -} -class SessionOptionValueFloat extends SessionOptionvalue { - private final float value; + class SessionOptionValueFloat extends SessionOptionvalue { + private final float value; - SessionOptionValueFloat(Float value) { - this.value = value; - } + SessionOptionValueFloat(Float value) { + this.value = value; + } - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -} - -class SessionOptionValueDouble extends SessionOptionvalue { + class SessionOptionValueDouble extends SessionOptionvalue { private final double value; - SessionOptionValueDouble(double value) { - this.value = value; - } + SessionOptionValueDouble(double value) { + this.value = value; + } - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } -} -class SessionOptionValueStringList extends SessionOptionvalue { - private final String[] value; - SessionOptionValueStringList(String[] value) { - this.value = value.clone(); - } + class SessionOptionValueStringList extends SessionOptionvalue { + private final String[] value; - void acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + SessionOptionValueStringList(String[] value) { + this.value = value.clone(); + } + + void acceptVisitor(SessionOptionValueVisitor v) { + v.visit(value); + } } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java index 6fd65fdb65801..8e562d3712428 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java @@ -19,6 +19,8 @@ /** * A visitor interface to access SessionOptionValue's contained value. + * + * @param Return type of the visit operation. */ public interface SessionOptionValueVisitor { /** From a73e8d26c23d926f87af40fe61dcaccfbeab4295 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sat, 9 Dec 2023 18:24:07 -0800 Subject: [PATCH 114/195] checkpoint --- .../arrow/flight/CloseSessionResult.java | 4 +- .../org/apache/arrow/flight/FlightClient.java | 4 +- .../flight/GetSessionOptionsRequest.java | 3 ++ .../arrow/flight/GetSessionOptionsResult.java | 1 + .../arrow/flight/SessionOptionValue.java | 29 ++++++------ .../flight/SessionOptionValueFactory.java | 45 ++++++++++--------- .../flight/SetSessionOptionsRequest.java | 6 ++- .../arrow/flight/SetSessionOptionsResult.java | 43 +++++++++++------- 8 files changed, 79 insertions(+), 56 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java index 7ddc767a32c8d..144546efae4dc 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java @@ -48,8 +48,8 @@ public enum Status { NOT_CLOSABLE, ; - public static Status fromProtocol(Flight.CloseSessionResult.Status s) { - return values()[t.ordinal()]; + public static Status fromProtocol(Flight.CloseSessionResult.Status proto) { + return values()[proto.ordinal()]; } public Flight.CloseSessionResult.Status toProtocol() { diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java index c96b12dc3f12e..973b3e560e88e 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java @@ -598,7 +598,7 @@ public SetSessionOptionsResult setSessionOptions(SetSessionOptionsRequest reques SetSessionOptionsResult result; try { - result = FlightEndpoint.deserialize(ByteBuffer.wrap(results.next().getBody())); + result = SetSessionOptionsResult.deserialize(ByteBuffer.wrap(results.next().getBody())); } catch (IOException | URISyntaxException e) { throw CallStatus.INTERNAL .withDescription("Failed to parse server response: " + e) @@ -626,7 +626,7 @@ public GetSessionOptionsResult getSessionOptions(SetSessionOptionsRequest reques .toRuntimeException(); } - FlightGetSessionOptionsResultEndpoint result; + GetSessionOptionsResult result; try { result = GetSessionOptionsResult.deserialize(ByteBuffer.wrap(results.next().getBody())); } catch (IOException e) { diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java index bc11d7de046f8..1609d8520b20f 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java @@ -22,6 +22,9 @@ import org.apache.arrow.flight.impl.Flight; +/** + * A request to get current session options. + */ public class GetSessionOptionsRequest { public GetSessionOptionsRequest() {} diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java index 337bd75474a4d..ccd5f9c76bc1d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index e685a187ad84e..6dbf39d944ec7 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -17,6 +17,8 @@ package org.apache.arrow.flight; +import java.util.Arrays; + import org.apache.arrow.flight.impl.Flight; /** @@ -26,7 +28,7 @@ public abstract class SessionOptionValue { /** * Value access via a caller-provided visitor/functor. */ - abstract T acceptVisitor(SessionOptionValueVisitor v); + public abstract T acceptVisitor(SessionOptionValueVisitor v); Flight.SessionOptionValue toProtocol() { Flight.SessionOptionValue.Builder b = Flight.SessionOptionValue.newBuilder(); @@ -38,44 +40,45 @@ Flight.SessionOptionValue toProtocol() { private class SessionOptionValueToProtocolVisitor implements SessionOptionValueVisitor { final Flight.SessionOptionValue.Builder b; - SessionOptionValueVisitor(Flight.SessionOptionValue.Builder b) { + SessionOptionValueToProtocolVisitor(Flight.SessionOptionValue.Builder b) { this.b = b; } - Void visit(String value) { + public Void visit(String value) { b.setStringValue(value); return null; } - Void visit(boolean value) { + public Void visit(boolean value) { b.setBoolValue(value); return null; } - Void visit(int value) { - b.setIn32Value(value); + public Void visit(int value) { + b.setInt32Value(value); return null; } - Void visit(long value) { + public Void visit(long value) { b.setInt64Value(value); return null; } - Void visit(float value) { + public Void visit(float value) { b.setFloatValue(value); return null; } - Void visit(double value) { + public Void visit(double value) { b.setDoubleValue(value); return null; } - Void visit(String[] value) { - Flight.SessionOptionValue.StringListValue pbValue; - pbValue.addAllStringValues(value); - b.setValue(pbValue); + public Void visit(String[] value) { + Flight.SessionOptionValue.StringListValue.Builder pbSLVBuilder = + Flight.SessionOptionValue.StringListValue.newBuilder(); + pbSLVBuilder.addAllValues(Arrays.asList(value)); + b.setStringListValue(pbSLVBuilder.build()); return null; } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 88f602c62870d..e0a7758a31388 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -19,13 +19,17 @@ import java.util.stream.Collectors; +import org.apache.arrow.flight.impl.Flight; + +import com.google.protobuf.StringValue; + /** Abstract factory for concrete SessionOptionValue instances. */ public class SessionOptionValueFactory { public static SessionOptionValue makeSessionOptionValue(String value) { return new SessionOptionValueString(value); } - public static SessionOptionValue makeSessionOptionValue(bool value) { + public static SessionOptionValue makeSessionOptionValue(boolean value) { return new SessionOptionValueBoolean(value); } @@ -49,14 +53,15 @@ public static SessionOptionValue makeSessionOptionValue(String[] value) { return new SessionOptionValueStringList(value); } + /** Construct a SessionOptionValue from its Protobuf object representation. */ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValue proto) { switch (proto.getOptionValueCase()) { case STRING_VALUE: return new SessionOptionValueString(proto.getStringValue()); case BOOL_VALUE: - return new SessionOptionValueBoolean(proto.getValue()); + return new SessionOptionValueBoolean(proto.getBoolValue()); case INT32_VALUE: - return new SessionOptionValueInteger(proto.getInt32Value()); + return new SessionOptionValueInt(proto.getInt32Value()); case INT64_VALUE: return new SessionOptionValueLong(proto.getInt64Value()); case FLOAT_VALUE: @@ -65,94 +70,94 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu return new SessionOptionValueDouble(proto.getDoubleValue()); case STRING_LIST_VALUE: // FIXME PHOXME is this what's in the ProtocolStringList? - return new SessionOptionValueStringList(proto.getValueStringList().stream().collect( - Collectors.toList(e -> google.protocol.StringValue.parseFrom(e).getValue()))); + return new SessionOptionValueStringList(proto.getStringListValue().getValuesList().asByteStringList().stream() + .map((e) -> StringValue.parseFrom(e).getValue()).collect(Collectors.toList())); default: // Unreachable throw new IllegalArgumentException(""); } } - class SessionOptionValueString extends SessionOptionvalue { + private static class SessionOptionValueString extends SessionOptionValue { private final String value; - SessionOptionValue(String value) { + SessionOptionValueString(String value) { this.value = value; } - void acceptVisitor(SessionOptionValueVisitor v) { + public T acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); } } - class SessionOptionValueBoolean extends SessionOptionvalue { + private static class SessionOptionValueBoolean extends SessionOptionValue { private final boolean value; SessionOptionValueBoolean(boolean value) { this.value = value; } - void acceptVisitor(SessionOptionValueVisitor v) { + public T acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); } } - class SessionOptionValueInt extends SessionOptionvalue { + private static class SessionOptionValueInt extends SessionOptionValue { private final int value; SessionOptionValueInt(int value) { this.value = value; } - void acceptVisitor(SessionOptionValueVisitor v) { + public T acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); } } - class SessionOptionValueLong extends SessionOptionvalue { + private static class SessionOptionValueLong extends SessionOptionValue { private final long value; SessionOptionValueLong(long value) { this.value = value; } - void acceptVisitor(SessionOptionValueVisitor v) { + public T acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); } } - class SessionOptionValueFloat extends SessionOptionvalue { + private static class SessionOptionValueFloat extends SessionOptionValue { private final float value; SessionOptionValueFloat(Float value) { this.value = value; } - void acceptVisitor(SessionOptionValueVisitor v) { + public T acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); } } - class SessionOptionValueDouble extends SessionOptionvalue { + private static class SessionOptionValueDouble extends SessionOptionValue { private final double value; SessionOptionValueDouble(double value) { this.value = value; } - void acceptVisitor(SessionOptionValueVisitor v) { + public T acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); } } - class SessionOptionValueStringList extends SessionOptionvalue { + private static class SessionOptionValueStringList extends SessionOptionValue { private final String[] value; SessionOptionValueStringList(String[] value) { this.value = value.clone(); } - void acceptVisitor(SessionOptionValueVisitor v) { + public T acceptVisitor(SessionOptionValueVisitor v) { v.visit(value); } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java index 01ec3188b9541..27515b5378cd0 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @@ -30,7 +31,7 @@ public class SetSessionOptionsRequest { private final Map sessionOptions; public SetSessionOptionsRequest(Map sessionOptions) { - this.sessionOptions = Collections.unmodifiableMap(new HashMap(sessionOptions)); + this.sessionOptions = Collections.unmodifiableMap(new HashMap(sessionOptions)); } SetSessionOptionsRequest(Flight.SetSessionOptionsRequest proto) { @@ -40,11 +41,12 @@ public SetSessionOptionsRequest(Map sessionOptions) } /** + * Get the session option map from the request. * * @return An immutable view of the session options map. */ public Map getSessionOptions() { - return new Collections.unmodifiableMap(sessionOptions); + return Collections.unmodifiableMap(sessionOptions); } Flight.SetSessionOptionsRequest toProtocol() { diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java index 830bdda7e5dc9..988f8289d8318 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; @@ -27,81 +28,89 @@ /** The result of attempting to set a set of session options. */ public class SetSessionOptionsResult { + /** Error status value for per-option errors. */ public enum ErrorValue { /** * The status of setting the option is unknown. Servers should avoid using this value * (send a NOT_FOUND error if the requested session is not known). Clients can retry * the request. */ - UNSPECIFIED(Flight.SetSessionOptionsResult.ErrorValue.UNSPECIFIED), + UNSPECIFIED, /** * The given session option name is invalid. */ - INVALID_NAME(Flight.SetSessionOptionsResult.ErrorValue.INVALID_NAME), + INVALID_NAME, /** * The session option value is invalid. */ - INVALID_VALUE(Flight.SetSessionOptionsResult.ErrorValue.INVALID_VALUE), + INVALID_VALUE, /** * The session option cannot be set. */ - ERROR(Flight.SetSessionOptionsResult.ErrorValue.ERROR), + ERROR, ; static ErrorValue fromProtocol(Flight.SetSessionOptionsResult.ErrorValue s) { return values()[s.ordinal()]; } - Flight.SetSessionOptionsResult.Status toProtocol() { + Flight.SetSessionOptionsResult.ErrorValue toProtocol() { return Flight.SetSessionOptionsResult.ErrorValue.values()[ordinal()]; } } + /** Per-option extensible error response container. */ public class Error { public ErrorValue value; - static Error fromProtocol(Flight.SetSessionOptionsResult.Error e) { - return Error(ErrorValue.fromProtocol(e.getValue())); + public Error(ErrorValue value) { + this.value = value; + } + + Error(Flight.SetSessionOptionsResult.Error e) { + value = ErrorValue.fromProtocol(e.getValue()); } Flight.SetSessionOptionsResult.Error toProtocol() { - Flight.SetSessionOptionsResult.Error b = Flight.SetSessionOptionsResult.newBuilder(); + Flight.SetSessionOptionsResult.Error.Builder b = Flight.SetSessionOptionsResult.Error.newBuilder(); b.setValue(value.toProtocol()); return b.build(); } } - private final Map errors; + private final Map errors; - public SetSessionOptionsResult(Map errors) { - this.errors = Collections.unmodifiableMap(new HashMap(errors)); + public SetSessionOptionsResult(Map errors) { + this.errors = Collections.unmodifiableMap(new HashMap(errors)); } SetSessionOptionsResult(Flight.SetSessionOptionsResult proto) { errors = Collections.unmodifiableMap(proto.getErrors().entrySet().stream().collect( - Collectors.toMap(Map.Entry::getKey, (e) -> Error.fromProtocol(e.getValue())))); + Collectors.toMap(Map.Entry::getKey, (e) -> new Error(e.getValue())))); } + /** Report whether the error map has nonzero length. */ public boolean hasErrors() { return errors.size() > 0; } /** + * Get the error status map from the result object. * * @return An immutable view of the error status map. */ - public Map getErrors() { + public Map getErrors() { return errors; } Flight.SetSessionOptionsResult toProtocol() { Flight.SetSessionOptionsResult.Builder b = Flight.SetSessionOptionsResult.newBuilder(); - b.putAllResults(errors.entrySet().stream().collect(Collectors.toMap( + b.putAllErrors(errors.entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, (e) -> { - Flight.SetSessionOptionsResult.Error.builder b = Flight.SetSessionOptionsResult.Error.newBuilder(); - b.setValue(Error.fromProtocol(e.getValue())); - return b.build(); } ))); + Flight.SetSessionOptionsResult.Error.Builder eb = Flight.SetSessionOptionsResult.Error.newBuilder(); + eb.setValue(e.getValue().toProtocol()); + return eb.build(); } ))); return b.build(); } From fa733149fbe611f26cc7bba5b65b3df763d58fe7 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sat, 9 Dec 2023 18:24:25 -0800 Subject: [PATCH 115/195] checkpoint --- .../org/apache/arrow/flight/SetSessionOptionsResult.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java index 988f8289d8318..63194e0a4096d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -107,10 +107,7 @@ Flight.SetSessionOptionsResult toProtocol() { Flight.SetSessionOptionsResult.Builder b = Flight.SetSessionOptionsResult.newBuilder(); b.putAllErrors(errors.entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, - (e) -> { - Flight.SetSessionOptionsResult.Error.Builder eb = Flight.SetSessionOptionsResult.Error.newBuilder(); - eb.setValue(e.getValue().toProtocol()); - return eb.build(); } ))); + (e) -> e.getValue().toProtocol()))); return b.build(); } From e6406cb728b7aca8bdef4776204acf2733646488 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sat, 9 Dec 2023 19:47:37 -0800 Subject: [PATCH 116/195] checkpoint - should be working but... --- .../flight/SessionOptionValueFactory.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index e0a7758a31388..ebcb82367f978 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -17,7 +17,7 @@ package org.apache.arrow.flight; -import java.util.stream.Collectors; +import java.lang.IOException; import org.apache.arrow.flight.impl.Flight; @@ -53,6 +53,16 @@ public static SessionOptionValue makeSessionOptionValue(String[] value) { return new SessionOptionValueStringList(value); } + /** Only use on Proto-generated ByteStrings that cannot fail parsing. */ + private static ByteStringToStringValueToStringOrNull(ByteString bs) { + try { + return StringValue.parseFrom(bs).getValue(); + } catch (java.lang.IOException e) { + // Unreachable, notwithstanding Proto bugs + return null; + } + } + /** Construct a SessionOptionValue from its Protobuf object representation. */ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValue proto) { switch (proto.getOptionValueCase()) { @@ -71,7 +81,7 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu case STRING_LIST_VALUE: // FIXME PHOXME is this what's in the ProtocolStringList? return new SessionOptionValueStringList(proto.getStringListValue().getValuesList().asByteStringList().stream() - .map((e) -> StringValue.parseFrom(e).getValue()).collect(Collectors.toList())); + .map(ByteStringToStringValueToStringOrNull).toArray(String[]::new)); default: // Unreachable throw new IllegalArgumentException(""); @@ -86,7 +96,7 @@ private static class SessionOptionValueString extends SessionOptionValue { } public T acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + return v.visit(value); } } @@ -98,7 +108,7 @@ private static class SessionOptionValueBoolean extends SessionOptionValue { } public T acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + return v.visit(value); } } @@ -110,7 +120,7 @@ private static class SessionOptionValueInt extends SessionOptionValue { } public T acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + return v.visit(value); } } @@ -122,7 +132,7 @@ private static class SessionOptionValueLong extends SessionOptionValue { } public T acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + return v.visit(value); } } @@ -134,7 +144,7 @@ private static class SessionOptionValueFloat extends SessionOptionValue { } public T acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + return v.visit(value); } } @@ -146,7 +156,7 @@ private static class SessionOptionValueDouble extends SessionOptionValue { } public T acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + return v.visit(value); } } @@ -158,7 +168,7 @@ private static class SessionOptionValueStringList extends SessionOptionValue { } public T acceptVisitor(SessionOptionValueVisitor v) { - v.visit(value); + return v.visit(value); } } } From 50bb521edf4b2bef701e6bb8b93a7b8a74cf0140 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sat, 9 Dec 2023 20:03:11 -0800 Subject: [PATCH 117/195] [builds] Prelim Java implementation --- .../arrow/flight/CloseSessionResult.java | 2 +- .../org/apache/arrow/flight/FlightClient.java | 2 +- .../flight/SessionOptionValueFactory.java | 22 +++++++++---------- .../arrow/flight/SetSessionOptionsResult.java | 2 +- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java index 144546efae4dc..88feab2b4c56d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java @@ -49,7 +49,7 @@ public enum Status { ; public static Status fromProtocol(Flight.CloseSessionResult.Status proto) { - return values()[proto.ordinal()]; + return values()[proto.getNumber()]; } public Flight.CloseSessionResult.Status toProtocol() { diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java index 973b3e560e88e..565fd9f4b096c 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java @@ -599,7 +599,7 @@ public SetSessionOptionsResult setSessionOptions(SetSessionOptionsRequest reques SetSessionOptionsResult result; try { result = SetSessionOptionsResult.deserialize(ByteBuffer.wrap(results.next().getBody())); - } catch (IOException | URISyntaxException e) { + } catch (IOException e) { throw CallStatus.INTERNAL .withDescription("Failed to parse server response: " + e) .withCause(e) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index ebcb82367f978..f7089f3ffe6ba 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -17,10 +17,11 @@ package org.apache.arrow.flight; -import java.lang.IOException; +import java.io.IOException; import org.apache.arrow.flight.impl.Flight; +//import com.google.protobuf.ByteString; import com.google.protobuf.StringValue; /** Abstract factory for concrete SessionOptionValue instances. */ @@ -53,16 +54,6 @@ public static SessionOptionValue makeSessionOptionValue(String[] value) { return new SessionOptionValueStringList(value); } - /** Only use on Proto-generated ByteStrings that cannot fail parsing. */ - private static ByteStringToStringValueToStringOrNull(ByteString bs) { - try { - return StringValue.parseFrom(bs).getValue(); - } catch (java.lang.IOException e) { - // Unreachable, notwithstanding Proto bugs - return null; - } - } - /** Construct a SessionOptionValue from its Protobuf object representation. */ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValue proto) { switch (proto.getOptionValueCase()) { @@ -81,7 +72,14 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu case STRING_LIST_VALUE: // FIXME PHOXME is this what's in the ProtocolStringList? return new SessionOptionValueStringList(proto.getStringListValue().getValuesList().asByteStringList().stream() - .map(ByteStringToStringValueToStringOrNull).toArray(String[]::new)); + .map((e) -> { + try { + return StringValue.parseFrom(e).getValue(); + } catch (IOException ignore) { + // Unreachable, notwithstanding Proto bugs + return null; + } + }).toArray(String[]::new)); default: // Unreachable throw new IllegalArgumentException(""); diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java index 63194e0a4096d..a22accbb437ce 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -51,7 +51,7 @@ public enum ErrorValue { ; static ErrorValue fromProtocol(Flight.SetSessionOptionsResult.ErrorValue s) { - return values()[s.ordinal()]; + return values()[s.getNumber()]; } Flight.SetSessionOptionsResult.ErrorValue toProtocol() { From e58742ede004dca6a2d2e0e8c8568f2917c09d8f Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sat, 9 Dec 2023 20:12:40 -0800 Subject: [PATCH 118/195] [builds] Prelim Java implementation --- .../java/org/apache/arrow/flight/SessionOptionValueFactory.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index f7089f3ffe6ba..db22d917d8365 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -70,7 +70,6 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu case DOUBLE_VALUE: return new SessionOptionValueDouble(proto.getDoubleValue()); case STRING_LIST_VALUE: - // FIXME PHOXME is this what's in the ProtocolStringList? return new SessionOptionValueStringList(proto.getStringListValue().getValuesList().asByteStringList().stream() .map((e) -> { try { From bc22b8015623c247ac163868d0565ad003b5cdf6 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 12 Dec 2023 12:52:53 -0800 Subject: [PATCH 119/195] [Java WIP]: Add nullable SessionOptionValue --- .../java/org/apache/arrow/flight/SessionOptionValue.java | 5 +++++ .../apache/arrow/flight/SessionOptionValueFactory.java | 8 ++++++++ .../apache/arrow/flight/SessionOptionValueVisitor.java | 8 ++++++++ 3 files changed, 21 insertions(+) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index 6dbf39d944ec7..8fde01526bbf0 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -81,5 +81,10 @@ public Void visit(String[] value) { b.setStringListValue(pbSLVBuilder.build()); return null; } + + public Void visit(Void ignored) { + // Proto SessionOptionValue builder is assumed to have its value unset. + return null; + } } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index db22d917d8365..890f8648958ee 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -79,6 +79,8 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu return null; } }).toArray(String[]::new)); + case OPTION_VALUE_NOT_SET: + return new SessionOptionValueEmpty(); default: // Unreachable throw new IllegalArgumentException(""); @@ -168,4 +170,10 @@ public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } } + + private static class SessionOptionValueEmpty extends SessionOptionValue { + public T acceptVisitor(SessionOptionValueVisitor v) { + return v.visit((Void) null); + } + } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java index 8e562d3712428..2c3d5cd794609 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java @@ -57,4 +57,12 @@ public interface SessionOptionValueVisitor { * A callback to handle SessionOptionValue containing an array of String. */ T visit(String[] value); + + /** + * A callback to handle SessionOptionValue containing no value. + * + * By convention, an attempt to set a valueless SessionOptionValue should + * attempt to unset or clear the named option v value on the server. + */ + T visit(Void value); } From 0df83a6c45e93df77741d063b768dc5a14720579 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 12 Dec 2023 13:04:00 -0800 Subject: [PATCH 120/195] fixup --- cpp/src/arrow/flight/types.h | 8 ++++++-- .../java/org/apache/arrow/flight/SessionOptionValue.java | 2 +- .../apache/arrow/flight/SessionOptionValueVisitor.java | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index f0848b60ebe18..161ba47465b2e 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -766,8 +766,12 @@ struct ARROW_FLIGHT_EXPORT CancelFlightInfoRequest { }; /// \brief Variant supporting all possible value types for {Set,Get}SessionOptions -using SessionOptionValue = std::variant>; +/// +/// By convention, an attempt to set a valueless (std::monostate) SessionOptionValue +/// should attempt to unset or clear the named option value on the server. +using SessionOptionValue = std::variant< + std::monostate, std::string, bool, int32_t, int64_t, float, double, + std::vector>; /// \brief The result of setting a session option. enum class SetSessionOptionErrorValue : int8_t { diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index 8fde01526bbf0..6b7c2b205d021 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -83,7 +83,7 @@ public Void visit(String[] value) { } public Void visit(Void ignored) { - // Proto SessionOptionValue builder is assumed to have its value unset. + b.clearOptionValue(); return null; } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java index 2c3d5cd794609..30feddb4bd2f6 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java @@ -62,7 +62,7 @@ public interface SessionOptionValueVisitor { * A callback to handle SessionOptionValue containing no value. * * By convention, an attempt to set a valueless SessionOptionValue should - * attempt to unset or clear the named option v value on the server. + * attempt to unset or clear the named option value on the server. */ T visit(Void value); } From 09c4369ae4623d3cd4496f8ec0795ec9c149c414 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 12 Dec 2023 13:29:01 -0800 Subject: [PATCH 121/195] [C++][builds] Add unset SessionOptionValue functionality --- .../arrow/flight/serialization_internal.cc | 27 ++++++++++--------- cpp/src/arrow/flight/types.cc | 12 ++++++++- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index faac1e4092463..602c0e2b42fa9 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -393,7 +393,8 @@ Status ToPayload(const FlightDescriptor& descr, std::shared_ptr* out) { Status FromProto(const pb::SessionOptionValue& pb_val, SessionOptionValue* val) { switch (pb_val.option_value_case()) { case pb::SessionOptionValue::OPTION_VALUE_NOT_SET: - return Status::Invalid("Unset SessionOptionValue found"); + *val = std::monostate{}; + break; case pb::SessionOptionValue::kStringValue: *val = pb_val.string_value(); break; @@ -424,17 +425,19 @@ Status FromProto(const pb::SessionOptionValue& pb_val, SessionOptionValue* val) } Status ToProto(const SessionOptionValue& val, pb::SessionOptionValue* pb_val) { - std::visit(overloaded{[&](std::string v) { pb_val->set_string_value(v); }, - [&](bool v) { pb_val->set_bool_value(v); }, - [&](int32_t v) { pb_val->set_int32_value(v); }, - [&](int64_t v) { pb_val->set_int64_value(v); }, - [&](float v) { pb_val->set_float_value(v); }, - [&](double v) { pb_val->set_double_value(v); }, - [&](std::vector v) { - auto* string_list_value = pb_val->mutable_string_list_value(); - for (const std::string& s : v) string_list_value->add_values(s); - }}, - val); + std::visit(overloaded{ + [&](std::monostate v) { pb_val->clear_option_value(); }, + [&](std::string v) { pb_val->set_string_value(v); }, + [&](bool v) { pb_val->set_bool_value(v); }, + [&](int32_t v) { pb_val->set_int32_value(v); }, + [&](int64_t v) { pb_val->set_int64_value(v); }, + [&](float v) { pb_val->set_float_value(v); }, + [&](double v) { pb_val->set_double_value(v); }, + [&](std::vector v) { + auto* string_list_value = pb_val->mutable_string_list_value(); + for (const std::string& s : v) string_list_value->add_values(s); + }}, + val); return Status::OK(); } diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index ef8f7e496b2a7..5cb36041fd1c2 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -512,7 +512,17 @@ std::ostream& operator<<(std::ostream& os, std::vector values) { } std::ostream& operator<<(std::ostream& os, const SessionOptionValue& v) { - std::visit([&](const auto& x) { os << x; }, v); + if (std::holds_alternative(v)) { + os << ""; + } else { + std::visit([&](const auto& x) { + if constexpr (std::is_convertible_v, std::string_view>) { + os << std::quoted(x); + } else { + os << x; + } + }, v); + } return os; } From 03da0121ea1b05826bd1070c2984e8bc0a742aa8 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 12 Dec 2023 15:32:15 -0800 Subject: [PATCH 122/195] [C++ builds][Java builds] typos/etc --- .../src/main/java/org/apache/arrow/flight/FlightClient.java | 4 ++-- .../org/apache/arrow/flight/SessionOptionValueFactory.java | 2 +- .../apache/arrow/flight/sql/CloseSessionResultListener.java | 4 ++-- .../java/org/apache/arrow/flight/sql/FlightSqlClient.java | 6 +++--- .../arrow/flight/sql/GetSessionOptionsResultListener.java | 4 ++-- .../arrow/flight/sql/SetSessionOptionsResultListener.java | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java index 565fd9f4b096c..3073c6339d17c 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java @@ -617,7 +617,7 @@ public SetSessionOptionsResult setSessionOptions(SetSessionOptionsRequest reques * @param options Call options. * @return The result containing the set of session options configured on the server. */ - public GetSessionOptionsResult getSessionOptions(SetSessionOptionsRequest request, CallOption... options) { + public GetSessionOptionsResult getSessionOptions(GetSessionOptionsRequest request, CallOption... options) { Action action = new Action(FlightConstants.GET_SESSION_OPTIONS.getType(), request.serialize().array()); Iterator results = doAction(action, options); if (!results.hasNext()) { @@ -647,7 +647,7 @@ public GetSessionOptionsResult getSessionOptions(SetSessionOptionsRequest reques * @param options Call options. * @return The result containing the status of the close operation. */ - public CloseSessionResult closeSession(SetSessionOptionsRequest request, CallOption... options) { + public CloseSessionResult closeSession(CloseSessionRequest request, CallOption... options) { Action action = new Action(FlightConstants.CLOSE_SESSION.getType(), request.serialize().array()); Iterator results = doAction(action, options); if (!results.hasNext()) { diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 890f8648958ee..db7c9379ec82d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -79,7 +79,7 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu return null; } }).toArray(String[]::new)); - case OPTION_VALUE_NOT_SET: + case OPTIONVALUE_NOT_SET: return new SessionOptionValueEmpty(); default: // Unreachable diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java index fd2b7838c15c0..5ebfa0becc106 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java @@ -22,10 +22,10 @@ import org.apache.arrow.flight.Result; /** Typed StreamListener for renewFlightEndpoint. */ -public class FlightEndpointListener implements FlightProducer.StreamListener { +public class CloseSessionResultListener implements FlightProducer.StreamListener { private final FlightProducer.StreamListener listener; - FlightEndpointListener(FlightProducer.StreamListener listener) { + CloseSessionResultListener(FlightProducer.StreamListener listener) { this.listener = listener; } diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlClient.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlClient.java index c2a82b149fe2c..e6eb28fe317e1 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlClient.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlClient.java @@ -924,15 +924,15 @@ public FlightEndpoint renewFlightEndpoint(RenewFlightEndpointRequest request, Ca } public SetSessionOptionsResult setSessionOptions(SetSessionOptionsRequest request, CallOption... options) { - return client.cancelFlightInfo(request, options); + return client.setSessionOptions(request, options); } public GetSessionOptionsResult getSessionOptions(GetSessionOptionsRequest request, CallOption... options) { - return client.cancelFlightInfo(request, options); + return client.getSessionOptions(request, options); } public CloseSessionResult closeSession(CloseSessionRequest request, CallOption... options) { - return client.cancelFlightInfo(request, options); + return client.closeSession(request, options); } @Override diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java index df3b65ec59c06..214a98464db71 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java @@ -22,10 +22,10 @@ import org.apache.arrow.flight.Result; /** Typed StreamListener for renewFlightEndpoint. */ -public class FlightEndpointListener implements FlightProducer.StreamListener { +public class GetSessionOptionsResultListener implements FlightProducer.StreamListener { private final FlightProducer.StreamListener listener; - FlightEndpointListener(FlightProducer.StreamListener listener) { + GetSessionOptionsResultListener(FlightProducer.StreamListener listener) { this.listener = listener; } diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java index 7992bfc432c4b..a13e1694c5fbc 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java @@ -22,10 +22,10 @@ import org.apache.arrow.flight.SetSessionOptionsResult; /** Typed StreamListener for renewFlightEndpoint. */ -public class FlightEndpointListener implements FlightProducer.StreamListener { +public class SetSessionOptionsResultListener implements FlightProducer.StreamListener { private final FlightProducer.StreamListener listener; - FlightEndpointListener(FlightProducer.StreamListener listener) { + SetSessionOptionsResultListener(FlightProducer.StreamListener listener) { this.listener = listener; } From 2bcc7213f37c76f7571bbc8b6f09b39dc5cdd19c Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 12 Dec 2023 15:48:47 -0800 Subject: [PATCH 123/195] Add Proto comment re: nullability --- format/Flight.proto | 3 +++ 1 file changed, 3 insertions(+) diff --git a/format/Flight.proto b/format/Flight.proto index 303209abfd5d1..721a41fe8e592 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -528,6 +528,9 @@ message PutResult { /* * EXPERIMENTAL: Union of possible value types for a Session Option to be set to. + * + * By convention, an attempt to set a valueless SessionOptionValue should + * attempt to unset or clear the named option value on the server. */ message SessionOptionValue { message StringListValue { From 93e974c23286142dbe444a7dc6d65a0a040a559b Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 12 Dec 2023 16:05:21 -0800 Subject: [PATCH 124/195] [C++][builds] Add braces --- cpp/src/arrow/flight/serialization_internal.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 602c0e2b42fa9..0549e1ac9b25c 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -413,13 +413,15 @@ Status FromProto(const pb::SessionOptionValue& pb_val, SessionOptionValue* val) case pb::SessionOptionValue::kDoubleValue: *val = pb_val.double_value(); break; - case pb::SessionOptionValue::kStringListValue: + case pb::SessionOptionValue::kStringListValue: { (*val).emplace>(); std::get>(*val).reserve( pb_val.string_list_value().values_size()); - for (const std::string& s : pb_val.string_list_value().values()) + for (const std::string& s : pb_val.string_list_value().values()) { std::get>(*val).push_back(s); + } break; + } } return Status::OK(); } From 479300a2d46ab4d048081a5a50cec7fe5de74a2f Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 12 Dec 2023 16:08:41 -0800 Subject: [PATCH 125/195] [C++][builds] Tiny refactor --- cpp/src/arrow/flight/serialization_internal.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 0549e1ac9b25c..d7ae6ee9bb327 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -414,12 +414,12 @@ Status FromProto(const pb::SessionOptionValue& pb_val, SessionOptionValue* val) *val = pb_val.double_value(); break; case pb::SessionOptionValue::kStringListValue: { - (*val).emplace>(); - std::get>(*val).reserve( - pb_val.string_list_value().values_size()); + std::vector vec; + vec.reserve(pb_val.string_list_value().values_size()); for (const std::string& s : pb_val.string_list_value().values()) { - std::get>(*val).push_back(s); + vec.push_back(s); } + (*val).emplace>(std::move(vec)); break; } } From 57f5ed3a029f07ac273118f9c62a58aea18efc53 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 12 Dec 2023 16:16:06 -0800 Subject: [PATCH 126/195] Update Proto comments re: HTTP-cookies-or-similar --- cpp/src/arrow/flight/serialization_internal.cc | 2 +- format/Flight.proto | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index d7ae6ee9bb327..06dff3539441e 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -450,7 +450,7 @@ Status FromProto(const google::protobuf::Map session_options = 1; @@ -588,8 +590,9 @@ message SetSessionOptionsResult { /* * EXPERIMENTAL: A request to access the session options for the current server session. * - * The existing session is referenced via a cookie header; it is an error to make this - * request with a missing, invalid, or expired session cookie header. + * The existing session is referenced via a cookie header or similar (see SetSessionOptionsRequest + * above); it is an error to make this request with a missing, invalid, or expired session cookie + * header or other implementation-defined session reference token. */ message GetSessionOptionsRequest { } From 90f1f81d346ca1da9999e0aa7493a6f9c94ce698 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 13 Dec 2023 18:03:14 -0800 Subject: [PATCH 127/195] checkpoint --- cpp/src/arrow/flight/sql/server_session_middleware.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 46268727a8873..39dd47dcfbcee 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -44,7 +44,7 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlSession { std::optional GetSessionOption(const std::string& name); /// \brief Set session option by name to given value void SetSessionOption(const std::string& name, const SessionOptionValue value); - /// \brief Idempotently remove key from this call's Session, if Session & name exist + /// \brief Idempotently remove name from this session void EraseSessionOption(const std::string& name); }; From c8ee267863f32bda70196c8ec05cabe520edacd3 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 18 Dec 2023 12:38:14 -0800 Subject: [PATCH 128/195] [Java builds] fixups --- .../java/org/apache/arrow/flight/SessionOptionValue.java | 8 ++++++++ .../apache/arrow/flight/SessionOptionValueFactory.java | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index 6b7c2b205d021..e92909d0d2729 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -44,36 +44,43 @@ private class SessionOptionValueToProtocolVisitor implements SessionOptionValueV this.b = b; } + @Override public Void visit(String value) { b.setStringValue(value); return null; } + @Override public Void visit(boolean value) { b.setBoolValue(value); return null; } + @Override public Void visit(int value) { b.setInt32Value(value); return null; } + @Override public Void visit(long value) { b.setInt64Value(value); return null; } + @Override public Void visit(float value) { b.setFloatValue(value); return null; } + @Override public Void visit(double value) { b.setDoubleValue(value); return null; } + @Override public Void visit(String[] value) { Flight.SessionOptionValue.StringListValue.Builder pbSLVBuilder = Flight.SessionOptionValue.StringListValue.newBuilder(); @@ -82,6 +89,7 @@ public Void visit(String[] value) { return null; } + @Override public Void visit(Void ignored) { b.clearOptionValue(); return null; diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index db7c9379ec82d..8cbaf981114b3 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -94,6 +94,7 @@ private static class SessionOptionValueString extends SessionOptionValue { this.value = value; } + @Override public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } @@ -106,6 +107,7 @@ private static class SessionOptionValueBoolean extends SessionOptionValue { this.value = value; } + @Override public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } @@ -118,6 +120,7 @@ private static class SessionOptionValueInt extends SessionOptionValue { this.value = value; } + @Override public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } @@ -130,6 +133,7 @@ private static class SessionOptionValueLong extends SessionOptionValue { this.value = value; } + @Override public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } @@ -142,6 +146,7 @@ private static class SessionOptionValueFloat extends SessionOptionValue { this.value = value; } + @Override public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } @@ -154,6 +159,7 @@ private static class SessionOptionValueDouble extends SessionOptionValue { this.value = value; } + @Override public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } @@ -166,12 +172,14 @@ private static class SessionOptionValueStringList extends SessionOptionValue { this.value = value.clone(); } + @Override public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } } private static class SessionOptionValueEmpty extends SessionOptionValue { + @Override public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit((Void) null); } From 5b587db6b580dfb046ef827cff222bff0fcea113 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 18 Dec 2023 12:38:49 -0800 Subject: [PATCH 129/195] [Java builds] Add ServerSessionMiddleware.java --- .../arrow/flight/ServerSessionMiddleware.java | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java new file mode 100644 index 0000000000000..100652c9cc86b --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java @@ -0,0 +1,188 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Middleware for handling Flight SQL Sessions including session cookie handling. + * + * Currently experimental. + */ +public class ServerSessionMiddleware implements FlightServerMiddleware { + Factory factory; + boolean existingSession; + private Session session; + + public static final String sessionCookieName = "arrow_flight_session_id"; + + /** + * Factory for managing and accessing ServerSessionMiddleware. + */ + public static class Factory implements FlightServerMiddleware.Factory { + private final Map sessionStore = + new ConcurrentHashMap<>(); + private final Callable idGenerator; + + /** + * Construct a factory for ServerSessionMiddleware. + * + * Factory manages and accesses persistent sessions based on HTTP cookies. + * + * @param idGenerator A Callable returning unique session id Strings. + */ + public Factory(Callable idGenerator) { + this.idGenerator = idGenerator; + } + + private synchronized Session createNewSession() { + String id; + try { + id = idGenerator.call(); + } catch (Exception ignored) { + // Most impls aren't going to throw so making caller handle a nonexistent checked is a bit silly + return null; + } + if (sessionStore.containsKey(id)) { + // Collision, should also never happen + return null; + } + + Session newSession = new Session(id); + sessionStore.put(id, newSession); + + return newSession; + } + + @Override + public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders incomingHeaders, + RequestContext context) { + String sessionId = null; + + findIdCookie: + for (final String headerValue : incomingHeaders.getAll("cookie")) { + for (final String cookie : headerValue.split(" ;")) { + final String[] cookiePair = cookie.split("="); + if (cookiePair.length != 2) { + // Soft failure: Ignore invalid cookie list field + break; + } + + if (cookiePair[0] == sessionCookieName && cookiePair[1].length() > 0) { + sessionId = cookiePair[1]; + break findIdCookie; + } + } + } + + if (sessionId == null) { + // No session cookie, create middleware instance without session. + return new ServerSessionMiddleware(this, incomingHeaders, null); + } + + Session session = sessionStore.get(sessionId); + // Cookie provided by caller, but invalid + if (session == null) { + // Can't soft-fail/proceed here, clients will get unexpected behaviour without options they thought were set. + throw new CallStatus( + FlightStatusCode.NOT_FOUND, null, + "Invalid or expired " + sessionCookieName + " cookie.", null) + .toRuntimeException(); + } + + return new ServerSessionMiddleware(this, incomingHeaders, session); + } + } + + /** + * A thread-safe container for named SessionOptionValues. + */ + public static class Session { + public final String id; + private Map session_data = + new ConcurrentHashMap(); + + /** + * Construct a new Session with the given id. + * + * @param id The Session's id string, which is used as the session cookie value. + */ + private Session(String id) { + this.id = id; + } + + /** Get session option by name, or null if it does not exist. */ + public SessionOptionValue getSessionOption(String name) { + return session_data.get(name); + } + + /** Set session option by name to given value. */ + public void setSessionOption(String name, SessionOptionValue value) { + session_data.put(name, value); + } + + /** Idempotently remove name from this session. */ + public void eraseSessionOption(String name) { + session_data.remove(name); + } + } + + private final CallHeaders headers; + + private ServerSessionMiddleware(ServerSessionMiddleware.Factory factory, + CallHeaders incomingHeaders, Session session) { + this.factory = factory; + headers = incomingHeaders; + this.session = session; + existingSession = (session != null); + } + + /** + * Get the existing or new session value map for this call. + * + * @return The session option value map, or null in case of an id generation collision. + */ + public synchronized Session getSession() { + if (session == null) { + session = factory.createNewSession(); + } + + return session; + } + + public CallHeaders getCallHeaders() { + return headers; + } + + @Override + public void onBeforeSendingHeaders(CallHeaders outgoingHeaders) { + if (!existingSession && session != null) { + outgoingHeaders.insert("set-cookie", sessionCookieName + "=" + session.id); + } + } + + @Override + public void onCallCompleted(CallStatus status) { + } + + @Override + public void onCallErrored(Throwable err) { + } +} From 23e71c3045201e8baad1a11f86575bed3311731c Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 22 Dec 2023 16:42:25 -0800 Subject: [PATCH 130/195] Fixup --- .../org/apache/arrow/flight/ServerSessionMiddleware.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java index 100652c9cc86b..6411164043c32 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java @@ -57,7 +57,7 @@ private synchronized Session createNewSession() { try { id = idGenerator.call(); } catch (Exception ignored) { - // Most impls aren't going to throw so making caller handle a nonexistent checked is a bit silly + // Most impls aren't going to throw so don't make caller handle a nonexistent checked exception return null; } if (sessionStore.containsKey(id)) { @@ -101,10 +101,7 @@ public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders inco // Cookie provided by caller, but invalid if (session == null) { // Can't soft-fail/proceed here, clients will get unexpected behaviour without options they thought were set. - throw new CallStatus( - FlightStatusCode.NOT_FOUND, null, - "Invalid or expired " + sessionCookieName + " cookie.", null) - .toRuntimeException(); + throw CallStatus.NOT_FOUND.withDescription("Invalid " + sessionCookieName + " cookie.").toRuntimeException(); } return new ServerSessionMiddleware(this, incomingHeaders, session); From f90f09eacb3c5c590b30e292047d4488f6731c0b Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 2 Jan 2024 15:16:01 -0800 Subject: [PATCH 131/195] checkpoint --- .../arrow/flight/ServerSessionMiddleware.java | 28 ++++++++++++++++--- .../arrow/flight/SessionOptionValue.java | 5 ++++ .../flight/SessionOptionValueFactory.java | 5 ++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java index 6411164043c32..34ac58cf969e5 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java @@ -17,6 +17,7 @@ package org.apache.arrow.flight; +import java.util.Collections; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; @@ -71,6 +72,12 @@ private synchronized Session createNewSession() { return newSession; } + private void closeSession(String id) { + if (sessionStore.remove(id) == null) { + throw CallStatus.NOT_FOUND.withDescription("Session id '" + id + "' not found.").toRuntimeException(); + } + } + @Override public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders incomingHeaders, RequestContext context) { @@ -113,7 +120,7 @@ public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders inco */ public static class Session { public final String id; - private Map session_data = + private Map sessionData = new ConcurrentHashMap(); /** @@ -127,17 +134,22 @@ private Session(String id) { /** Get session option by name, or null if it does not exist. */ public SessionOptionValue getSessionOption(String name) { - return session_data.get(name); + return sessionData.get(name); + } + + /** Get an immutable copy of the session options map. */ + public Map getSessionOptions() { + return Collections.unmodifiableMap(new HashMap(sessionData)); } /** Set session option by name to given value. */ public void setSessionOption(String name, SessionOptionValue value) { - session_data.put(name, value); + sessionData.put(name, value); } /** Idempotently remove name from this session. */ public void eraseSessionOption(String name) { - session_data.remove(name); + sessionData.remove(name); } } @@ -164,6 +176,14 @@ public synchronized Session getSession() { return session; } + public synchronized void closeSession() { + if (session == null) { + throw CallStatus.NOT_FOUND.withDescription("No session found for the current call.").toRuntimeException(); + } + factory.closeSession(session.id); + session = null; + } + public CallHeaders getCallHeaders() { return headers; } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index e92909d0d2729..4c1c54d7ce4e1 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -37,6 +37,11 @@ Flight.SessionOptionValue toProtocol() { return b.build(); } + /** Check whether the SessionOptionValue is empty/valueless. */ + public boolean isEmpty() { + return false; + } + private class SessionOptionValueToProtocolVisitor implements SessionOptionValueVisitor { final Flight.SessionOptionValue.Builder b; diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 8cbaf981114b3..7b13d1bd9ce3d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -183,5 +183,10 @@ private static class SessionOptionValueEmpty extends SessionOptionValue { public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit((Void) null); } + + @Override + public boolean isEmpty() { + return true; + } } } From f9afd1c4149bc6f1222b894a09756be2e1362097 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 2 Jan 2024 15:16:37 -0800 Subject: [PATCH 132/195] checkpoint --- .../tests/SessionOptionsProducer.java | 72 +++++++++++++++++++ .../tests/SessionOptionsScenario.java | 24 +++++++ 2 files changed, 96 insertions(+) create mode 100644 java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java create mode 100644 java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java new file mode 100644 index 0000000000000..933f46f600f1a --- /dev/null +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java @@ -0,0 +1,72 @@ +/* + * 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. + */ + +package org.apache.arrow.flight.integration.tests; + +import java.util.*; + +import org.apache.arrow.flight.*; +import org.apache.arrow.flight.sql.NoOpFlightSqlProducer; +import org.apache.arrow.memory.BufferAllocator; + +/** The server used for testing Sessions. + *

+ * SetSessionOptions(), GetSessionOptions(), and CloseSession() operate on a + * simple SessionOptionValue store. + */ +final class SessionOptionsProducer extends NoOpFlightSqlProducer { + private final BufferAllocator allocator; + private final FlightServerMiddleware.Key sessionMiddlewareKey; + + SessionOptionsProducer(FlightServerMiddleware.Key sessionMiddlewareKey) { + this.sessionMiddlewareKey = sessionMiddlewareKey; + } + + @Override + void setSessionOptions(SetSessionOptionsRequest request, CallContext context, + StreamListener listener) { + Map errors = new HashMap(); + + ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); + ServerSessionMiddleware.Session session = middleware.getSession(); + for (Map.Entry entry : request.getSessionOptions().entrySet()) { + // TODO consider adding immutable value collisions, name blacklist, value/value-type whitelists, etc. + if (entry.getValue().isEmpty()) { + session.eraseSessionOption(entry.getKey()); + continue; + } + session.setSessionOption(entry.getKey(), entry.getValue()); + } + + return new SetSessionOptionsResult(errors); + } + + @Override + void getSessionOptions(GetSessionOptionsRequest request, CallContext context, + StreamListener listener) { + ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); + final Map sessionOptions = middleware.getSession().getSessionOptions(); + return new GetSessionOptionsResult(sessionOptions); + } + + @Override + void closeSession(CloseSessionRequest request, CallContext context, + StreamListener listener) { + ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); + middleware.closeSession(); + } +} \ No newline at end of file diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java new file mode 100644 index 0000000000000..a335ae0569b36 --- /dev/null +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -0,0 +1,24 @@ +package org.apache.arrow.flight.integration.tests; + +import org.apache.arrow.flight.*; +import org.apache.arrow.memory.BufferAllocator; + +final class SessionOptionsScenario implements Scenario { + // TODO this needs to be at Scenario scope (& not static) + private final FlightServerMiddleware.Key key = + FlightServerMiddleware.Key.of("sessionmiddleware"); + + public FlightProducer producer(BufferAllocator allocator, Location location) throws Exception { + return new SessionOptionsProducer(key); + } + + @Override + public void buildServer(FlightServer.Builder builder) { + builder.middleware(key, new ServerSessionMiddleware.Factory()); + } + + @Override + public void client(BufferAllocator allocator, Location location, FlightClient client) throws Exception { + // TODO PHOXME + } +} \ No newline at end of file From 6d3f2c0707dfa6219e090005e27ef66d25a19f29 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 2 Jan 2024 16:03:05 -0800 Subject: [PATCH 133/195] checkpoint --- .../flight/SessionOptionValueFactory.java | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 7b13d1bd9ce3d..43be2581a2e25 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -18,6 +18,7 @@ package org.apache.arrow.flight; import java.io.IOException; +import java.util.Arrays; import org.apache.arrow.flight.impl.Flight; @@ -98,6 +99,28 @@ private static class SessionOptionValueString extends SessionOptionValue { public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SessionOptionValueString that = (SessionOptionValueString) o; + return value == that.value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public String toString() { + return '"' + value + '"'; + } } private static class SessionOptionValueBoolean extends SessionOptionValue { @@ -111,6 +134,28 @@ private static class SessionOptionValueBoolean extends SessionOptionValue { public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SessionOptionValueBoolean that = (SessionOptionValueBoolean) o; + return value == that.value; + } + + @Override + public int hashCode() { + return Boolean.hashCode(value); + } + + @Override + public String toString() { + return String.valueOf(value); + } } private static class SessionOptionValueInt extends SessionOptionValue { @@ -124,6 +169,28 @@ private static class SessionOptionValueInt extends SessionOptionValue { public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SessionOptionValueInt that = (SessionOptionValueInt) o; + return value == that.value; + } + + @Override + public int hashCode() { + return Integer.hashCode(value); + } + + @Override + public String toString() { + return String.valueOf(value); + } } private static class SessionOptionValueLong extends SessionOptionValue { @@ -137,6 +204,28 @@ private static class SessionOptionValueLong extends SessionOptionValue { public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SessionOptionValueLong that = (SessionOptionValueLong) o; + return value == that.value; + } + + @Override + public int hashCode() { + return Long.hashCode(value); + } + + @Override + public String toString() { + return String.valueOf(value); + } } private static class SessionOptionValueFloat extends SessionOptionValue { @@ -150,6 +239,28 @@ private static class SessionOptionValueFloat extends SessionOptionValue { public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SessionOptionValueFloat that = (SessionOptionValueFloat) o; + return value == that.value; + } + + @Override + public int hashCode() { + return Float.hashCode(value); + } + + @Override + public String toString() { + return String.valueOf(value); + } } private static class SessionOptionValueDouble extends SessionOptionValue { @@ -163,6 +274,28 @@ private static class SessionOptionValueDouble extends SessionOptionValue { public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SessionOptionValueDouble that = (SessionOptionValueDouble) o; + return value == that.value; + } + + @Override + public int hashCode() { + return Double.hashCode(value); + } + + @Override + public String toString() { + return String.valueOf(value); + } } private static class SessionOptionValueStringList extends SessionOptionValue { @@ -176,6 +309,31 @@ private static class SessionOptionValueStringList extends SessionOptionValue { public T acceptVisitor(SessionOptionValueVisitor v) { return v.visit(value); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SessionOptionValueStringList that = (SessionOptionValueStringList) o; + return Arrays.deepEquals(value, that.value); + } + + @Override + public int hashCode() { + return Boolean.hashCode(value); + } + + @Override + public String toString() { + if (value.length == 0) { + return "[]"; + } + return "[\"" + String.join("\", \"", value) + "\"]"; + } } private static class SessionOptionValueEmpty extends SessionOptionValue { @@ -188,5 +346,26 @@ public T acceptVisitor(SessionOptionValueVisitor v) { public boolean isEmpty() { return true; } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return Arrays.deepHashCode(value); + } + + @Override + public String toString() { + return ""; + } } } From 6d7769346d0a995e00b35f2fd63fec0eb0b969a1 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 2 Jan 2024 16:52:28 -0800 Subject: [PATCH 134/195] checkpoint --- .../flight/integration/tests/Scenarios.java | 1 + .../tests/SessionOptionsScenario.java | 31 +++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/Scenarios.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/Scenarios.java index c61fd94a4d228..6878c22c5ccdc 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/Scenarios.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/Scenarios.java @@ -50,6 +50,7 @@ private Scenarios() { scenarios.put("flight_sql", FlightSqlScenario::new); scenarios.put("flight_sql:extension", FlightSqlExtensionScenario::new); scenarios.put("app_metadata_flight_info_endpoint", AppMetadataFlightInfoEndpointScenario::new); + scenarios.put("session_options", SessionOptionsScenario::new); } private static Scenarios getInstance() { diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index a335ae0569b36..1d403f4e9b9f9 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -1,10 +1,28 @@ +/* + * 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. + */ + package org.apache.arrow.flight.integration.tests; import org.apache.arrow.flight.*; +import org.apache.arrow.flight.client.ClientCookieMiddleware; +import org.apache.arrow.flight.sql.FlightSqlClient; import org.apache.arrow.memory.BufferAllocator; final class SessionOptionsScenario implements Scenario { - // TODO this needs to be at Scenario scope (& not static) private final FlightServerMiddleware.Key key = FlightServerMiddleware.Key.of("sessionmiddleware"); @@ -18,7 +36,16 @@ public void buildServer(FlightServer.Builder builder) { } @Override - public void client(BufferAllocator allocator, Location location, FlightClient client) throws Exception { + public void client(BufferAllocator allocator, Location location, FlightClient ignored) throws Exception { // TODO PHOXME + + final ClientCookieMiddleware.Factory factory = new ClientCookieMiddleware.Factory(); + try (final FlightClient flightClient = FlightClient.builder(allocator, location).intercept(factory).build()) { + final FlightSqlClient client = new FlightSqlClient(client); + + // No existing session yet + IntegrationAssertions.assertThrows(FlightRuntimeException.class, + () -> client.getSessionOptions(new GetSessionOptionsRequest())); + } } } \ No newline at end of file From a00cf2aef3b5624c533b72c87801ed0a5ed44aae Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 3 Jan 2024 15:01:08 -0800 Subject: [PATCH 135/195] [Java builds] Add initial Java integration tests --- .../arrow/flight/ServerSessionMiddleware.java | 6 +++ .../flight/SessionOptionValueFactory.java | 4 +- .../tests/SessionOptionsProducer.java | 38 ++++++++++++------- .../tests/SessionOptionsScenario.java | 27 +++++++++---- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java index 34ac58cf969e5..359e36b9ce988 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java @@ -18,6 +18,7 @@ package org.apache.arrow.flight; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; @@ -176,6 +177,11 @@ public synchronized Session getSession() { return session; } + /** + * Close the current session. + * + * It is an error to call this without a session specified via cookie or equivalent. + * */ public synchronized void closeSession() { if (session == null) { throw CallStatus.NOT_FOUND.withDescription("No session found for the current call.").toRuntimeException(); diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 43be2581a2e25..0b4f89fcacbed 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -324,7 +324,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Boolean.hashCode(value); + return Arrays.deepHashCode(value); } @Override @@ -360,7 +360,7 @@ public boolean equals(Object o) { @Override public int hashCode() { - return Arrays.deepHashCode(value); + return SessionOptionValueEmpty.class.hashCode(); } @Override diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java index 933f46f600f1a..1b19662c64642 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java @@ -17,11 +17,19 @@ package org.apache.arrow.flight.integration.tests; -import java.util.*; +import java.util.HashMap; +import java.util.Map; -import org.apache.arrow.flight.*; +import org.apache.arrow.flight.CloseSessionRequest; +import org.apache.arrow.flight.CloseSessionResult; +import org.apache.arrow.flight.FlightServerMiddleware; +import org.apache.arrow.flight.GetSessionOptionsRequest; +import org.apache.arrow.flight.GetSessionOptionsResult; +import org.apache.arrow.flight.ServerSessionMiddleware; +import org.apache.arrow.flight.SessionOptionValue; +import org.apache.arrow.flight.SetSessionOptionsRequest; +import org.apache.arrow.flight.SetSessionOptionsResult; import org.apache.arrow.flight.sql.NoOpFlightSqlProducer; -import org.apache.arrow.memory.BufferAllocator; /** The server used for testing Sessions. *

@@ -29,7 +37,6 @@ * simple SessionOptionValue store. */ final class SessionOptionsProducer extends NoOpFlightSqlProducer { - private final BufferAllocator allocator; private final FlightServerMiddleware.Key sessionMiddlewareKey; SessionOptionsProducer(FlightServerMiddleware.Key sessionMiddlewareKey) { @@ -37,8 +44,8 @@ final class SessionOptionsProducer extends NoOpFlightSqlProducer { } @Override - void setSessionOptions(SetSessionOptionsRequest request, CallContext context, - StreamListener listener) { + public void setSessionOptions(SetSessionOptionsRequest request, CallContext context, + StreamListener listener) { Map errors = new HashMap(); ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); @@ -51,22 +58,25 @@ void setSessionOptions(SetSessionOptionsRequest request, CallContext context, } session.setSessionOption(entry.getKey(), entry.getValue()); } - - return new SetSessionOptionsResult(errors); + listener.onNext(new SetSessionOptionsResult(errors)); + listener.onCompleted(); } @Override - void getSessionOptions(GetSessionOptionsRequest request, CallContext context, - StreamListener listener) { + public void getSessionOptions(GetSessionOptionsRequest request, CallContext context, + StreamListener listener) { ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); final Map sessionOptions = middleware.getSession().getSessionOptions(); - return new GetSessionOptionsResult(sessionOptions); + listener.onNext(new GetSessionOptionsResult(sessionOptions)); + listener.onCompleted(); } @Override - void closeSession(CloseSessionRequest request, CallContext context, - StreamListener listener) { + public void closeSession(CloseSessionRequest request, CallContext context, + StreamListener listener) { ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); middleware.closeSession(); + listener.onNext(new CloseSessionResult(CloseSessionResult.Status.CLOSED)); + listener.onCompleted(); } -} \ No newline at end of file +} diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index 1d403f4e9b9f9..f4b4844887fd9 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -17,14 +17,26 @@ package org.apache.arrow.flight.integration.tests; -import org.apache.arrow.flight.*; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.arrow.flight.FlightClient; +import org.apache.arrow.flight.FlightProducer; +import org.apache.arrow.flight.FlightRuntimeException; +import org.apache.arrow.flight.FlightServer; +import org.apache.arrow.flight.FlightServerMiddleware; +import org.apache.arrow.flight.GetSessionOptionsRequest; +import org.apache.arrow.flight.Location; +import org.apache.arrow.flight.ServerSessionMiddleware; import org.apache.arrow.flight.client.ClientCookieMiddleware; import org.apache.arrow.flight.sql.FlightSqlClient; import org.apache.arrow.memory.BufferAllocator; +/** + * Scenario to exercise Session Options functionality. + */ final class SessionOptionsScenario implements Scenario { private final FlightServerMiddleware.Key key = - FlightServerMiddleware.Key.of("sessionmiddleware"); + FlightServerMiddleware.Key.of("sessionmiddleware"); public FlightProducer producer(BufferAllocator allocator, Location location) throws Exception { return new SessionOptionsProducer(key); @@ -32,20 +44,21 @@ public FlightProducer producer(BufferAllocator allocator, Location location) thr @Override public void buildServer(FlightServer.Builder builder) { - builder.middleware(key, new ServerSessionMiddleware.Factory()); + AtomicInteger counter = new AtomicInteger(1000); + builder.middleware(key, new ServerSessionMiddleware.Factory(() -> String.valueOf(counter.getAndIncrement()))); } @Override public void client(BufferAllocator allocator, Location location, FlightClient ignored) throws Exception { - // TODO PHOXME + // TODO PHOXME add more interesting cases`` final ClientCookieMiddleware.Factory factory = new ClientCookieMiddleware.Factory(); try (final FlightClient flightClient = FlightClient.builder(allocator, location).intercept(factory).build()) { - final FlightSqlClient client = new FlightSqlClient(client); + final FlightSqlClient client = new FlightSqlClient(flightClient); // No existing session yet IntegrationAssertions.assertThrows(FlightRuntimeException.class, - () -> client.getSessionOptions(new GetSessionOptionsRequest())); + () -> client.getSessionOptions(new GetSessionOptionsRequest())); } } -} \ No newline at end of file +} From f473c797ab2f098ac93cf2e8e14745d95d5315bc Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 3 Jan 2024 15:32:15 -0800 Subject: [PATCH 136/195] [C++] clang-format fixups --- .../arrow/flight/serialization_internal.cc | 25 +++++++++---------- cpp/src/arrow/flight/types.cc | 24 ++++++++++-------- cpp/src/arrow/flight/types.h | 5 ++-- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 06dff3539441e..c610b6dfc6442 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -427,19 +427,18 @@ Status FromProto(const pb::SessionOptionValue& pb_val, SessionOptionValue* val) } Status ToProto(const SessionOptionValue& val, pb::SessionOptionValue* pb_val) { - std::visit(overloaded{ - [&](std::monostate v) { pb_val->clear_option_value(); }, - [&](std::string v) { pb_val->set_string_value(v); }, - [&](bool v) { pb_val->set_bool_value(v); }, - [&](int32_t v) { pb_val->set_int32_value(v); }, - [&](int64_t v) { pb_val->set_int64_value(v); }, - [&](float v) { pb_val->set_float_value(v); }, - [&](double v) { pb_val->set_double_value(v); }, - [&](std::vector v) { - auto* string_list_value = pb_val->mutable_string_list_value(); - for (const std::string& s : v) string_list_value->add_values(s); - }}, - val); + std::visit(overloaded{[&](std::monostate v) { pb_val->clear_option_value(); }, + [&](std::string v) { pb_val->set_string_value(v); }, + [&](bool v) { pb_val->set_bool_value(v); }, + [&](int32_t v) { pb_val->set_int32_value(v); }, + [&](int64_t v) { pb_val->set_int64_value(v); }, + [&](float v) { pb_val->set_float_value(v); }, + [&](double v) { pb_val->set_double_value(v); }, + [&](std::vector v) { + auto* string_list_value = pb_val->mutable_string_list_value(); + for (const std::string& s : v) string_list_value->add_values(s); + }}, + val); return Status::OK(); } diff --git a/cpp/src/arrow/flight/types.cc b/cpp/src/arrow/flight/types.cc index 5cb36041fd1c2..11b2baafad220 100644 --- a/cpp/src/arrow/flight/types.cc +++ b/cpp/src/arrow/flight/types.cc @@ -475,8 +475,8 @@ arrow::Result CancelFlightInfoRequest::Deserialize( return out; } -static const char* const SetSessionOptionStatusNames[] = { - "Unspecified", "InvalidName", "InvalidValue", "Error"}; +static const char* const SetSessionOptionStatusNames[] = {"Unspecified", "InvalidName", + "InvalidValue", "Error"}; static const char* const CloseSessionStatusNames[] = {"Unspecified", "Closed", "Closing", "NotClosable"}; @@ -485,7 +485,8 @@ std::string ToString(const SetSessionOptionErrorValue& error_value) { return SetSessionOptionStatusNames[static_cast(error_value)]; } -std::ostream& operator<<(std::ostream& os, const SetSessionOptionErrorValue& error_value) { +std::ostream& operator<<(std::ostream& os, + const SetSessionOptionErrorValue& error_value) { os << ToString(error_value); return os; } @@ -515,13 +516,16 @@ std::ostream& operator<<(std::ostream& os, const SessionOptionValue& v) { if (std::holds_alternative(v)) { os << ""; } else { - std::visit([&](const auto& x) { - if constexpr (std::is_convertible_v, std::string_view>) { - os << std::quoted(x); - } else { - os << x; - } - }, v); + std::visit( + [&](const auto& x) { + if constexpr (std::is_convertible_v, + std::string_view>) { + os << std::quoted(x); + } else { + os << x; + } + }, + v); } return os; } diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 161ba47465b2e..a7b2cd954f82b 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -769,9 +769,8 @@ struct ARROW_FLIGHT_EXPORT CancelFlightInfoRequest { /// /// By convention, an attempt to set a valueless (std::monostate) SessionOptionValue /// should attempt to unset or clear the named option value on the server. -using SessionOptionValue = std::variant< - std::monostate, std::string, bool, int32_t, int64_t, float, double, - std::vector>; +using SessionOptionValue = std::variant>; /// \brief The result of setting a session option. enum class SetSessionOptionErrorValue : int8_t { From 55c200b03054725fbf8b3458291b0ef776b77460 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 3 Jan 2024 15:50:46 -0800 Subject: [PATCH 137/195] [C++] clang-format fixup --- cpp/src/arrow/flight/serialization_internal.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index c610b6dfc6442..796199a88e8c9 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -438,7 +438,7 @@ Status ToProto(const SessionOptionValue& val, pb::SessionOptionValue* pb_val) { auto* string_list_value = pb_val->mutable_string_list_value(); for (const std::string& s : v) string_list_value->add_values(s); }}, - val); + val); return Status::OK(); } From 5e1306a403464bf8f34498811932a7ab0a07058c Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 5 Jan 2024 14:01:40 -0800 Subject: [PATCH 138/195] [Java builds] Add and fix initial working Java integration test --- .../arrow/flight/ServerSessionMiddleware.java | 38 ++++++++++++------- .../tests/SessionOptionsProducer.java | 14 ++++++- .../integration/tests/IntegrationTest.java | 5 +++ 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java index 359e36b9ce988..91c57f368e77b 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java @@ -84,18 +84,21 @@ public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders inco RequestContext context) { String sessionId = null; - findIdCookie: - for (final String headerValue : incomingHeaders.getAll("cookie")) { - for (final String cookie : headerValue.split(" ;")) { - final String[] cookiePair = cookie.split("="); - if (cookiePair.length != 2) { - // Soft failure: Ignore invalid cookie list field - break; - } - - if (cookiePair[0] == sessionCookieName && cookiePair[1].length() > 0) { - sessionId = cookiePair[1]; - break findIdCookie; + final Iterable it = incomingHeaders.getAll("cookie"); + if (it != null) { + findIdCookie: + for (final String headerValue : it) { + for (final String cookie : headerValue.split(" ;")) { + final String[] cookiePair = cookie.split("="); + if (cookiePair.length != 2) { + // Soft failure: Ignore invalid cookie list field + break; + } + + if (cookiePair[0] == sessionCookieName && cookiePair[1].length() > 0) { + sessionId = cookiePair[1]; + break findIdCookie; + } } } } @@ -164,6 +167,15 @@ private ServerSessionMiddleware(ServerSessionMiddleware.Factory factory, existingSession = (session != null); } + /** + * Check if there is an open session associated with this call. + * + * @return True iff there is an open session associated with this call. + */ + public boolean hasSession() { + return session != null; + } + /** * Get the existing or new session value map for this call. * @@ -180,7 +192,7 @@ public synchronized Session getSession() { /** * Close the current session. * - * It is an error to call this without a session specified via cookie or equivalent. + * It is an error to call this without a valid session specified via cookie or equivalent. * */ public synchronized void closeSession() { if (session == null) { diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java index 1b19662c64642..3dcb6bfc1dc9c 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java @@ -20,8 +20,10 @@ import java.util.HashMap; import java.util.Map; +import org.apache.arrow.flight.CallStatus; import org.apache.arrow.flight.CloseSessionRequest; import org.apache.arrow.flight.CloseSessionResult; +import org.apache.arrow.flight.FlightRuntimeException; import org.apache.arrow.flight.FlightServerMiddleware; import org.apache.arrow.flight.GetSessionOptionsRequest; import org.apache.arrow.flight.GetSessionOptionsResult; @@ -66,6 +68,11 @@ public void setSessionOptions(SetSessionOptionsRequest request, CallContext cont public void getSessionOptions(GetSessionOptionsRequest request, CallContext context, StreamListener listener) { ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); + if (!middleware.hasSession()) { + // Attempt to get options without an existing session + listener.onError(CallStatus.NOT_FOUND.withDescription("No current server session").toRuntimeException()); + return; + } final Map sessionOptions = middleware.getSession().getSessionOptions(); listener.onNext(new GetSessionOptionsResult(sessionOptions)); listener.onCompleted(); @@ -75,7 +82,12 @@ public void getSessionOptions(GetSessionOptionsRequest request, CallContext cont public void closeSession(CloseSessionRequest request, CallContext context, StreamListener listener) { ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); - middleware.closeSession(); + try { + middleware.closeSession(); + } catch (FlightRuntimeException fre) { + listener.onError(fre); + return; + } listener.onNext(new CloseSessionResult(CloseSessionResult.Status.CLOSED)); listener.onCompleted(); } diff --git a/java/flight/flight-integration-tests/src/test/java/org/apache/arrow/flight/integration/tests/IntegrationTest.java b/java/flight/flight-integration-tests/src/test/java/org/apache/arrow/flight/integration/tests/IntegrationTest.java index 477a56055cbbc..f814427567ae9 100644 --- a/java/flight/flight-integration-tests/src/test/java/org/apache/arrow/flight/integration/tests/IntegrationTest.java +++ b/java/flight/flight-integration-tests/src/test/java/org/apache/arrow/flight/integration/tests/IntegrationTest.java @@ -83,6 +83,11 @@ void appMetadataFlightInfoEndpoint() throws Exception { testScenario("app_metadata_flight_info_endpoint"); } + @Test + void sessionOptions() throws Exception { + testScenario("session_options"); + } + void testScenario(String scenarioName) throws Exception { try (final BufferAllocator allocator = new RootAllocator()) { final FlightServer.Builder builder = FlightServer.builder() From cceff9595ce491f885c9fc02af48ea42a7b07e85 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 10 Jan 2024 12:08:36 -0800 Subject: [PATCH 139/195] [Java builds] Expand SessionOptionsProducer to facilitate more tests --- .../arrow/flight/SetSessionOptionsResult.java | 2 +- .../tests/SessionOptionsProducer.java | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java index a22accbb437ce..48e56c77e6780 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -60,7 +60,7 @@ Flight.SetSessionOptionsResult.ErrorValue toProtocol() { } /** Per-option extensible error response container. */ - public class Error { + public static class Error { public ErrorValue value; public Error(ErrorValue value) { diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java index 3dcb6bfc1dc9c..9e62417f8ec11 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java @@ -29,6 +29,7 @@ import org.apache.arrow.flight.GetSessionOptionsResult; import org.apache.arrow.flight.ServerSessionMiddleware; import org.apache.arrow.flight.SessionOptionValue; +import org.apache.arrow.flight.SessionOptionValueFactory; import org.apache.arrow.flight.SetSessionOptionsRequest; import org.apache.arrow.flight.SetSessionOptionsResult; import org.apache.arrow.flight.sql.NoOpFlightSqlProducer; @@ -39,6 +40,8 @@ * simple SessionOptionValue store. */ final class SessionOptionsProducer extends NoOpFlightSqlProducer { + private static final SessionOptionValue invalidOptionValue = + SessionOptionValueFactory.makeSessionOptionValue("lol_invalid"); private final FlightServerMiddleware.Key sessionMiddlewareKey; SessionOptionsProducer(FlightServerMiddleware.Key sessionMiddlewareKey) { @@ -53,7 +56,18 @@ public void setSessionOptions(SetSessionOptionsRequest request, CallContext cont ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); ServerSessionMiddleware.Session session = middleware.getSession(); for (Map.Entry entry : request.getSessionOptions().entrySet()) { - // TODO consider adding immutable value collisions, name blacklist, value/value-type whitelists, etc. + // Blacklisted value name + if (entry.getKey().equals("lol_invalid")) { + errors.put(entry.getKey(), new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)); + continue; + } + // Blacklisted value + // Recommend using a visitor to check polymorphic equality, but this check is easy + if (entry.getValue().equals(invalidOptionValue)) { + errors.put(entry.getKey(), new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_VALUE)); + continue; + } + // Business as usual: if (entry.getValue().isEmpty()) { session.eraseSessionOption(entry.getKey()); continue; From e4ea62f62b3da4cc14992125d0c29c2021ee143b Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 10 Jan 2024 17:13:40 -0800 Subject: [PATCH 140/195] WIP --- .../arrow/flight/GetSessionOptionsResult.java | 2 +- .../arrow/flight/ServerSessionMiddleware.java | 5 ++- .../flight/SessionOptionValueFactory.java | 7 +++- .../flight/SetSessionOptionsRequest.java | 2 +- .../arrow/flight/SetSessionOptionsResult.java | 17 +++++++++ .../tests/SessionOptionsScenario.java | 36 +++++++++++++++++++ 6 files changed, 65 insertions(+), 4 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java index ccd5f9c76bc1d..c777bd39bd032 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsResult.java @@ -36,7 +36,7 @@ public GetSessionOptionsResult(Map sessionOptions) { GetSessionOptionsResult(Flight.GetSessionOptionsResult proto) { sessionOptions = Collections.unmodifiableMap( - proto.getSessionOptions().entrySet().stream().collect(Collectors.toMap( + proto.getSessionOptionsMap().entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, (e) -> SessionOptionValueFactory.makeSessionOptionValue(e.getValue())))); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java index 91c57f368e77b..d7e5bd5439c3b 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java @@ -95,7 +95,7 @@ public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders inco break; } - if (cookiePair[0] == sessionCookieName && cookiePair[1].length() > 0) { + if (sessionCookieName.equals(cookiePair[0]) && cookiePair[1].length() > 0) { sessionId = cookiePair[1]; break findIdCookie; } @@ -104,6 +104,7 @@ public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders inco } if (sessionId == null) { + System.err.println("************* No session cookie found"); // No session cookie, create middleware instance without session. return new ServerSessionMiddleware(this, incomingHeaders, null); } @@ -111,10 +112,12 @@ public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders inco Session session = sessionStore.get(sessionId); // Cookie provided by caller, but invalid if (session == null) { + System.err.println("************* Invalid session cookie found, throwing NOT_FOUND"); // Can't soft-fail/proceed here, clients will get unexpected behaviour without options they thought were set. throw CallStatus.NOT_FOUND.withDescription("Invalid " + sessionCookieName + " cookie.").toRuntimeException(); } + System.err.println("************* Session found by cookie and loaded into call-local middleware instance"); return new ServerSessionMiddleware(this, incomingHeaders, session); } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 0b4f89fcacbed..3e2e7dea8a0ec 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -55,6 +55,10 @@ public static SessionOptionValue makeSessionOptionValue(String[] value) { return new SessionOptionValueStringList(value); } + public static SessionOptionValue makeEmptySessionOptionValue() { + return new SessionOptionValueEmpty(); + } + /** Construct a SessionOptionValue from its Protobuf object representation. */ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValue proto) { switch (proto.getOptionValueCase()) { @@ -102,6 +106,7 @@ public T acceptVisitor(SessionOptionValueVisitor v) { @Override public boolean equals(Object o) { + System.err.println("************* TESTING STRING VALUE EQUALITY"); // FIXME PHOXME remove this if (this == o) { return true; } @@ -109,7 +114,7 @@ public boolean equals(Object o) { return false; } SessionOptionValueString that = (SessionOptionValueString) o; - return value == that.value; + return value.equals(that.value); } @Override diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java index 27515b5378cd0..8a5253e682162 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsRequest.java @@ -36,7 +36,7 @@ public SetSessionOptionsRequest(Map sessionOptions) SetSessionOptionsRequest(Flight.SetSessionOptionsRequest proto) { sessionOptions = Collections.unmodifiableMap( - proto.getSessionOptions().entrySet().stream().collect(Collectors.toMap( + proto.getSessionOptionsMap().entrySet().stream().collect(Collectors.toMap( Map.Entry::getKey, (e) -> SessionOptionValueFactory.makeSessionOptionValue(e.getValue())))); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java index 48e56c77e6780..b250375e39228 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -76,6 +76,23 @@ Flight.SetSessionOptionsResult.Error toProtocol() { b.setValue(value.toProtocol()); return b.build(); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Error that = (Error) o; + return value == that.value; + } + + @Override + public int hashCode() { + return value.hashCode(); + } } private final Map errors; diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index f4b4844887fd9..3a610e45a315b 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -17,6 +17,7 @@ package org.apache.arrow.flight.integration.tests; +import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; import org.apache.arrow.flight.FlightClient; @@ -25,8 +26,13 @@ import org.apache.arrow.flight.FlightServer; import org.apache.arrow.flight.FlightServerMiddleware; import org.apache.arrow.flight.GetSessionOptionsRequest; +import org.apache.arrow.flight.GetSessionOptionsResult; import org.apache.arrow.flight.Location; import org.apache.arrow.flight.ServerSessionMiddleware; +import org.apache.arrow.flight.SessionOptionValue; +import org.apache.arrow.flight.SessionOptionValueFactory; +import org.apache.arrow.flight.SetSessionOptionsRequest; +import org.apache.arrow.flight.SetSessionOptionsResult; import org.apache.arrow.flight.client.ClientCookieMiddleware; import org.apache.arrow.flight.sql.FlightSqlClient; import org.apache.arrow.memory.BufferAllocator; @@ -38,6 +44,7 @@ final class SessionOptionsScenario implements Scenario { private final FlightServerMiddleware.Key key = FlightServerMiddleware.Key.of("sessionmiddleware"); + @Override public FlightProducer producer(BufferAllocator allocator, Location location) throws Exception { return new SessionOptionsProducer(key); } @@ -59,6 +66,35 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig // No existing session yet IntegrationAssertions.assertThrows(FlightRuntimeException.class, () -> client.getSessionOptions(new GetSessionOptionsRequest())); + + SetSessionOptionsRequest req1 = new SetSessionOptionsRequest(new HashMap() { + { + put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)); + put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)); + put("lol_invalid", SessionOptionValueFactory.makeSessionOptionValue("this won't get set")); + put("key_with_invalid_value", SessionOptionValueFactory.makeSessionOptionValue("lol_invalid")); + put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( + new String[]{"a", "b", "sea", "dee", " ", " ", "geee"})); + } + }); + SetSessionOptionsResult res1 = client.setSessionOptions(req1); + IntegrationAssertions.assertEquals(new HashMap() { + { + put("lol_invalid", new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)); + put("key_with_invalid_value", new SetSessionOptionsResult.Error( + SetSessionOptionsResult.ErrorValue.INVALID_VALUE)); + } + }, res1.getErrors()); + + GetSessionOptionsResult res2 = client.getSessionOptions(new GetSessionOptionsRequest()); + IntegrationAssertions.assertEquals(res2.getSessionOptions(), new HashMap() { + { + put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)); + put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)); + put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( + new String[]{"a", "b", "sea", "dee", " ", " ", "geee"})); + } + }); } } } From 91337d82811b9db2abd1fafb0d0b35a9ddd8aac1 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 10 Jan 2024 21:27:40 -0800 Subject: [PATCH 141/195] checkpoint --- .../arrow/flight/ServerSessionMiddleware.java | 3 -- .../flight/SessionOptionValueFactory.java | 15 ++---- .../tests/SessionOptionsProducer.java | 49 +++++++++++-------- .../tests/SessionOptionsScenario.java | 2 - 4 files changed, 31 insertions(+), 38 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java index d7e5bd5439c3b..990ea34b3d3fd 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java @@ -104,7 +104,6 @@ public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders inco } if (sessionId == null) { - System.err.println("************* No session cookie found"); // No session cookie, create middleware instance without session. return new ServerSessionMiddleware(this, incomingHeaders, null); } @@ -112,12 +111,10 @@ public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders inco Session session = sessionStore.get(sessionId); // Cookie provided by caller, but invalid if (session == null) { - System.err.println("************* Invalid session cookie found, throwing NOT_FOUND"); // Can't soft-fail/proceed here, clients will get unexpected behaviour without options they thought were set. throw CallStatus.NOT_FOUND.withDescription("Invalid " + sessionCookieName + " cookie.").toRuntimeException(); } - System.err.println("************* Session found by cookie and loaded into call-local middleware instance"); return new ServerSessionMiddleware(this, incomingHeaders, session); } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 3e2e7dea8a0ec..d1433e9678d3a 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -17,13 +17,11 @@ package org.apache.arrow.flight; -import java.io.IOException; import java.util.Arrays; import org.apache.arrow.flight.impl.Flight; -//import com.google.protobuf.ByteString; -import com.google.protobuf.StringValue; +import com.google.protobuf.ByteString; /** Abstract factory for concrete SessionOptionValue instances. */ public class SessionOptionValueFactory { @@ -75,15 +73,9 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu case DOUBLE_VALUE: return new SessionOptionValueDouble(proto.getDoubleValue()); case STRING_LIST_VALUE: + // Using ByteString::toByteArray() here otherwise we still somehow get `ByteArray`s with broken .equals(String) return new SessionOptionValueStringList(proto.getStringListValue().getValuesList().asByteStringList().stream() - .map((e) -> { - try { - return StringValue.parseFrom(e).getValue(); - } catch (IOException ignore) { - // Unreachable, notwithstanding Proto bugs - return null; - } - }).toArray(String[]::new)); + .map(ByteString::toByteArray).toArray(String[]::new)); case OPTIONVALUE_NOT_SET: return new SessionOptionValueEmpty(); default: @@ -106,7 +98,6 @@ public T acceptVisitor(SessionOptionValueVisitor v) { @Override public boolean equals(Object o) { - System.err.println("************* TESTING STRING VALUE EQUALITY"); // FIXME PHOXME remove this if (this == o) { return true; } diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java index 9e62417f8ec11..1c0aca5f32a5d 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java @@ -51,30 +51,37 @@ final class SessionOptionsProducer extends NoOpFlightSqlProducer { @Override public void setSessionOptions(SetSessionOptionsRequest request, CallContext context, StreamListener listener) { - Map errors = new HashMap(); + try { + Map errors = new HashMap(); - ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); - ServerSessionMiddleware.Session session = middleware.getSession(); - for (Map.Entry entry : request.getSessionOptions().entrySet()) { - // Blacklisted value name - if (entry.getKey().equals("lol_invalid")) { - errors.put(entry.getKey(), new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)); - continue; - } - // Blacklisted value - // Recommend using a visitor to check polymorphic equality, but this check is easy - if (entry.getValue().equals(invalidOptionValue)) { - errors.put(entry.getKey(), new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_VALUE)); - continue; - } - // Business as usual: - if (entry.getValue().isEmpty()) { - session.eraseSessionOption(entry.getKey()); - continue; + ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); + ServerSessionMiddleware.Session session = middleware.getSession(); + for (Map.Entry entry : request.getSessionOptions().entrySet()) { + // Blacklisted value name + if (entry.getKey().equals("lol_invalid")) { + errors.put(entry.getKey(), + new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)); + continue; + } + // Blacklisted value + // Recommend using a visitor to check polymorphic equality, but this check is easy + if (entry.getValue().equals(invalidOptionValue)) { + errors.put(entry.getKey(), + new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_VALUE)); + continue; + } + // Business as usual: + if (entry.getValue().isEmpty()) { + session.eraseSessionOption(entry.getKey()); + continue; + } + session.setSessionOption(entry.getKey(), entry.getValue()); } - session.setSessionOption(entry.getKey(), entry.getValue()); + listener.onNext(new SetSessionOptionsResult(errors)); + } catch (Exception e) { + System.err.println("Caught exception from somewhere in setSessionOptions handler code:"); + e.printStackTrace(); } - listener.onNext(new SetSessionOptionsResult(errors)); listener.onCompleted(); } diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index 3a610e45a315b..fb11dab18b287 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -57,8 +57,6 @@ public void buildServer(FlightServer.Builder builder) { @Override public void client(BufferAllocator allocator, Location location, FlightClient ignored) throws Exception { - // TODO PHOXME add more interesting cases`` - final ClientCookieMiddleware.Factory factory = new ClientCookieMiddleware.Factory(); try (final FlightClient flightClient = FlightClient.builder(allocator, location).intercept(factory).build()) { final FlightSqlClient client = new FlightSqlClient(flightClient); From 261be0377615b61a61b202bebaf456d42fab7cfa Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 11 Jan 2024 01:24:00 -0800 Subject: [PATCH 142/195] [Java builds & passes] fix up integration tests & related code --- .../flight/SessionOptionValueFactory.java | 4 +--- .../arrow/flight/sql/FlightSqlProducer.java | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index d1433e9678d3a..96eba7b0ad39e 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -21,8 +21,6 @@ import org.apache.arrow.flight.impl.Flight; -import com.google.protobuf.ByteString; - /** Abstract factory for concrete SessionOptionValue instances. */ public class SessionOptionValueFactory { public static SessionOptionValue makeSessionOptionValue(String value) { @@ -75,7 +73,7 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu case STRING_LIST_VALUE: // Using ByteString::toByteArray() here otherwise we still somehow get `ByteArray`s with broken .equals(String) return new SessionOptionValueStringList(proto.getStringListValue().getValuesList().asByteStringList().stream() - .map(ByteString::toByteArray).toArray(String[]::new)); + .map((e) -> new String(e.toByteArray())).toArray(String[]::new)); case OPTIONVALUE_NOT_SET: return new SessionOptionValueEmpty(); default: diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java index 0d6ee782fd70f..5739d8c943fb2 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java @@ -390,17 +390,22 @@ default void doAction(CallContext context, Action action, StreamListener } renewFlightEndpoint(request, context, new FlightEndpointListener(listener)); } else if (actionType.equals(FlightConstants.SET_SESSION_OPTIONS.getType())) { - final SetSessionOptionsRequest request; try { - request = SetSessionOptionsRequest.deserialize(ByteBuffer.wrap(action.getBody())); - } catch (IOException e) { - listener.onError(CallStatus.INTERNAL - .withDescription("Could not unpack SetSessionOptionsRequest: " + e) - .withCause(e) - .toRuntimeException()); - return; + final SetSessionOptionsRequest request; + try { + request = SetSessionOptionsRequest.deserialize(ByteBuffer.wrap(action.getBody())); + } catch (IOException e) { + listener.onError(CallStatus.INTERNAL + .withDescription("Could not unpack SetSessionOptionsRequest: " + e) + .withCause(e) + .toRuntimeException()); + return; + } + setSessionOptions(request, context, new SetSessionOptionsResultListener(listener)); + } catch (Exception e) { // FIXME PHOXME remove + System.err.println("Caught exception outside of setSessionOptions handler:"); + e.printStackTrace(); } - setSessionOptions(request, context, new SetSessionOptionsResultListener(listener)); } else if (actionType.equals(FlightConstants.GET_SESSION_OPTIONS.getType())) { final GetSessionOptionsRequest request; try { From e171643703a6429517f59c3229cfd142b80a8948 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 11 Jan 2024 11:56:03 -0800 Subject: [PATCH 143/195] [Java builds & passes] Fix & add Unicode integration test coverage --- .../flight/SessionOptionValueFactory.java | 3 ++- .../tests/SessionOptionsScenario.java | 8 +++---- .../arrow/flight/sql/FlightSqlProducer.java | 23 ++++++++----------- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 96eba7b0ad39e..7edb7a7e55ee9 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -17,6 +17,7 @@ package org.apache.arrow.flight; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import org.apache.arrow.flight.impl.Flight; @@ -73,7 +74,7 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu case STRING_LIST_VALUE: // Using ByteString::toByteArray() here otherwise we still somehow get `ByteArray`s with broken .equals(String) return new SessionOptionValueStringList(proto.getStringListValue().getValuesList().asByteStringList().stream() - .map((e) -> new String(e.toByteArray())).toArray(String[]::new)); + .map((e) -> new String(e.toByteArray(), StandardCharsets.UTF_8)).toArray(String[]::new)); case OPTIONVALUE_NOT_SET: return new SessionOptionValueEmpty(); default: diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index fb11dab18b287..1806261c73f38 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -72,7 +72,7 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig put("lol_invalid", SessionOptionValueFactory.makeSessionOptionValue("this won't get set")); put("key_with_invalid_value", SessionOptionValueFactory.makeSessionOptionValue("lol_invalid")); put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( - new String[]{"a", "b", "sea", "dee", " ", " ", "geee"})); + new String[]{"a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"})); } }); SetSessionOptionsResult res1 = client.setSessionOptions(req1); @@ -85,14 +85,14 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig }, res1.getErrors()); GetSessionOptionsResult res2 = client.getSessionOptions(new GetSessionOptionsRequest()); - IntegrationAssertions.assertEquals(res2.getSessionOptions(), new HashMap() { + IntegrationAssertions.assertEquals(new HashMap() { { put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)); put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)); put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( - new String[]{"a", "b", "sea", "dee", " ", " ", "geee"})); + new String[]{"a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"})); } - }); + }, res2.getSessionOptions()); } } } diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java index 5739d8c943fb2..0d6ee782fd70f 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java @@ -390,22 +390,17 @@ default void doAction(CallContext context, Action action, StreamListener } renewFlightEndpoint(request, context, new FlightEndpointListener(listener)); } else if (actionType.equals(FlightConstants.SET_SESSION_OPTIONS.getType())) { + final SetSessionOptionsRequest request; try { - final SetSessionOptionsRequest request; - try { - request = SetSessionOptionsRequest.deserialize(ByteBuffer.wrap(action.getBody())); - } catch (IOException e) { - listener.onError(CallStatus.INTERNAL - .withDescription("Could not unpack SetSessionOptionsRequest: " + e) - .withCause(e) - .toRuntimeException()); - return; - } - setSessionOptions(request, context, new SetSessionOptionsResultListener(listener)); - } catch (Exception e) { // FIXME PHOXME remove - System.err.println("Caught exception outside of setSessionOptions handler:"); - e.printStackTrace(); + request = SetSessionOptionsRequest.deserialize(ByteBuffer.wrap(action.getBody())); + } catch (IOException e) { + listener.onError(CallStatus.INTERNAL + .withDescription("Could not unpack SetSessionOptionsRequest: " + e) + .withCause(e) + .toRuntimeException()); + return; } + setSessionOptions(request, context, new SetSessionOptionsResultListener(listener)); } else if (actionType.equals(FlightConstants.GET_SESSION_OPTIONS.getType())) { final GetSessionOptionsRequest request; try { From ca2a1e44ea3693beca268da89b50ac2846af023d Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 11 Jan 2024 13:22:08 -0800 Subject: [PATCH 144/195] [Java builds & passes] ServerSessionMiddleware.CloseSession: expire cookie --- .../org/apache/arrow/flight/ServerSessionMiddleware.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java index 990ea34b3d3fd..1f599ca99b07b 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java @@ -32,6 +32,7 @@ public class ServerSessionMiddleware implements FlightServerMiddleware { Factory factory; boolean existingSession; private Session session; + private String closedSessionId = null; public static final String sessionCookieName = "arrow_flight_session_id"; @@ -199,6 +200,7 @@ public synchronized void closeSession() { throw CallStatus.NOT_FOUND.withDescription("No session found for the current call.").toRuntimeException(); } factory.closeSession(session.id); + closedSessionId = session.id; session = null; } @@ -211,6 +213,9 @@ public void onBeforeSendingHeaders(CallHeaders outgoingHeaders) { if (!existingSession && session != null) { outgoingHeaders.insert("set-cookie", sessionCookieName + "=" + session.id); } + if (closedSessionId != null) { + outgoingHeaders.insert("set-cookie", sessionCookieName + "=" + closedSessionId + "; Max-Age=0"); + } } @Override From cf5f74f1b1f648760351c3e8005b0322068b8c79 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 11 Jan 2024 18:03:42 -0800 Subject: [PATCH 145/195] [Java builds & passes] Finish Java integration tests --- .../arrow/flight/CloseSessionResult.java | 2 +- .../tests/SessionOptionsProducer.java | 51 +++++++++---------- .../tests/SessionOptionsScenario.java | 36 ++++++++++++- 3 files changed, 59 insertions(+), 30 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java index 88feab2b4c56d..c3710a14b108a 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionResult.java @@ -71,7 +71,7 @@ public CloseSessionResult(Status status) { } } - Status getStatus() { + public Status getStatus() { return status; } diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java index 1c0aca5f32a5d..b4b34f584627d 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java @@ -51,37 +51,32 @@ final class SessionOptionsProducer extends NoOpFlightSqlProducer { @Override public void setSessionOptions(SetSessionOptionsRequest request, CallContext context, StreamListener listener) { - try { - Map errors = new HashMap(); + Map errors = new HashMap(); - ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); - ServerSessionMiddleware.Session session = middleware.getSession(); - for (Map.Entry entry : request.getSessionOptions().entrySet()) { - // Blacklisted value name - if (entry.getKey().equals("lol_invalid")) { - errors.put(entry.getKey(), - new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)); - continue; - } - // Blacklisted value - // Recommend using a visitor to check polymorphic equality, but this check is easy - if (entry.getValue().equals(invalidOptionValue)) { - errors.put(entry.getKey(), - new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_VALUE)); - continue; - } - // Business as usual: - if (entry.getValue().isEmpty()) { - session.eraseSessionOption(entry.getKey()); - continue; - } - session.setSessionOption(entry.getKey(), entry.getValue()); + ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); + ServerSessionMiddleware.Session session = middleware.getSession(); + for (Map.Entry entry : request.getSessionOptions().entrySet()) { + // Blacklisted value name + if (entry.getKey().equals("lol_invalid")) { + errors.put(entry.getKey(), + new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)); + continue; + } + // Blacklisted value + // Recommend using a visitor to check polymorphic equality, but this check is easy + if (entry.getValue().equals(invalidOptionValue)) { + errors.put(entry.getKey(), + new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_VALUE)); + continue; + } + // Business as usual: + if (entry.getValue().isEmpty()) { + session.eraseSessionOption(entry.getKey()); + continue; } - listener.onNext(new SetSessionOptionsResult(errors)); - } catch (Exception e) { - System.err.println("Caught exception from somewhere in setSessionOptions handler code:"); - e.printStackTrace(); + session.setSessionOption(entry.getKey(), entry.getValue()); } + listener.onNext(new SetSessionOptionsResult(errors)); listener.onCompleted(); } diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index 1806261c73f38..d85584fb35768 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -20,6 +20,8 @@ import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; +import org.apache.arrow.flight.CloseSessionRequest; +import org.apache.arrow.flight.CloseSessionResult; import org.apache.arrow.flight.FlightClient; import org.apache.arrow.flight.FlightProducer; import org.apache.arrow.flight.FlightRuntimeException; @@ -65,6 +67,7 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig IntegrationAssertions.assertThrows(FlightRuntimeException.class, () -> client.getSessionOptions(new GetSessionOptionsRequest())); + // Set SetSessionOptionsRequest req1 = new SetSessionOptionsRequest(new HashMap() { { put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)); @@ -76,6 +79,7 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig } }); SetSessionOptionsResult res1 = client.setSessionOptions(req1); + // Some errors IntegrationAssertions.assertEquals(new HashMap() { { put("lol_invalid", new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)); @@ -83,7 +87,7 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig SetSessionOptionsResult.ErrorValue.INVALID_VALUE)); } }, res1.getErrors()); - + // Some set, some omitted due to errors GetSessionOptionsResult res2 = client.getSessionOptions(new GetSessionOptionsRequest()); IntegrationAssertions.assertEquals(new HashMap() { { @@ -93,6 +97,36 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig new String[]{"a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"})); } }, res2.getSessionOptions()); + // Update + client.setSessionOptions(new SetSessionOptionsRequest(new HashMap() { + { + // Delete + put("foolong", SessionOptionValueFactory.makeEmptySessionOptionValue()); + // Update + put("big_ol_string_list", + SessionOptionValueFactory.makeSessionOptionValue("a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ")); + } + })); + GetSessionOptionsResult res4 = client.getSessionOptions(new GetSessionOptionsRequest()); + IntegrationAssertions.assertEquals(new HashMap() { + { + put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)); + put("big_ol_string_list", + SessionOptionValueFactory.makeSessionOptionValue("a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ")); + } + }, res4.getSessionOptions()); + // Close + CloseSessionResult res5 = client.closeSession(new CloseSessionRequest()); + IntegrationAssertions.assertEquals(CloseSessionResult.Status.CLOSED, res5.getStatus()); + // Session should be defunct and cookie expired from cookie jar. + IntegrationAssertions.assertThrows(FlightRuntimeException.class, + () -> client.getSessionOptions(new GetSessionOptionsRequest())); + // This should create a new, empty session + SetSessionOptionsResult res6 = + client.setSessionOptions(new SetSessionOptionsRequest(new HashMap())); + GetSessionOptionsResult res7 = client.getSessionOptions(new GetSessionOptionsRequest()); + // This should be empty to confirm we have a new session, not reusing the same one somehow + IntegrationAssertions.assertEquals(new HashMap(), res7.getSessionOptions()); } } } From 0baa248a84bae76c2d5dba73bc17ff20cf9a0a03 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 12 Jan 2024 11:02:58 -0800 Subject: [PATCH 146/195] [C++ builds] Factor ServerSessionMiddleware to separate header for testability --- .../flight/sql/server_session_middleware.cc | 21 +------ .../flight/sql/server_session_middleware.h | 1 + .../sql/server_session_middleware_factory.h | 55 +++++++++++++++++++ 3 files changed, 57 insertions(+), 20 deletions(-) create mode 100644 cpp/src/arrow/flight/sql/server_session_middleware_factory.h diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index af9ba7e5083db..a492b2ab63e91 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -18,31 +18,12 @@ #include #include "arrow/flight/sql/server_session_middleware.h" +#include "arrow/flight/sql/server_session_middleware_factory.h" namespace arrow { namespace flight { namespace sql { -/// \brief A factory for ServerSessionMiddleware, itself storing session data. -class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { - protected: - std::map> session_store_; - std::shared_mutex session_store_lock_; - std::function id_generator_; - - std::vector> ParseCookieString( - const std::string_view& s); - - public: - explicit ServerSessionMiddlewareFactory(std::function id_gen) - : id_generator_(id_gen) {} - Status StartCall(const CallInfo&, const CallHeaders& incoming_headers, - std::shared_ptr* middleware); - - /// \brief Get a new, empty session option map and its id key. - std::pair> CreateNewSession(); -}; - class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { protected: std::shared_mutex mutex_; diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 39dd47dcfbcee..e9dbb6a19d92b 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -21,6 +21,7 @@ #pragma once #include +#include #include #include #include diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h new file mode 100644 index 0000000000000..4e3d72676f51e --- /dev/null +++ b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h @@ -0,0 +1,55 @@ +// 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. + +// ServerSessionMiddlewareFactory, factored into a separate header for testability + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace arrow { +namespace flight { +namespace sql { + +/// \brief A factory for ServerSessionMiddleware, itself storing session data. +class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { + protected: + std::map> session_store_; + std::shared_mutex session_store_lock_; + std::function id_generator_; + + std::vector> ParseCookieString( + const std::string_view& s); + + public: + explicit ServerSessionMiddlewareFactory(std::function id_gen) + : id_generator_(id_gen) {} + Status StartCall(const CallInfo&, const CallHeaders& incoming_headers, + std::shared_ptr* middleware); + + /// \brief Get a new, empty session option map and its id key. + std::pair> CreateNewSession(); +}; + +} // namespace sql +} // namespace flight +} // namespace arrow From c7975ec40575b31433b61d6096b449d44eb4e314 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 14 Jan 2024 18:49:56 -0800 Subject: [PATCH 147/195] [temp] Add dummy C++ unit test --- ...erver_session_middleware_internals_test.cc | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc new file mode 100644 index 0000000000000..faa4cb366264e --- /dev/null +++ b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc @@ -0,0 +1,41 @@ +// 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. + +// ---------------------------------------------------------------------- +// ServerSessionMiddleware{,Factory} tests not involing a client/server instance + +#include + +#include + +namespace arrow { +namespace flight { +namespace sql { + +class ServerSessionMiddlewareFactoryPrivate : public ServerSessionMiddlewareFactory { + public: + using ServerSessionMiddlewareFactory::ParseCookieString; +} + +TEST(ServerSessionMiddleware, Dummy) { + ASSERT_EQ(1, 1); +} + +} // namespace sql +} // namespace flight +} // namespace arrow + From e17d0db83a90c87bc9070a6063fc122fb11cba38 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 14 Jan 2024 19:07:03 -0800 Subject: [PATCH 148/195] [temp][fixup] Add dummy C++ unit test --- .../flight/sql/server_session_middleware_internals_test.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc index faa4cb366264e..93f162e280318 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc @@ -32,10 +32,9 @@ class ServerSessionMiddlewareFactoryPrivate : public ServerSessionMiddlewareFact } TEST(ServerSessionMiddleware, Dummy) { - ASSERT_EQ(1, 1); + ASSERT_EQ(1, 1); } } // namespace sql } // namespace flight } // namespace arrow - From 55c6864366cfbf3f69611c166423da178add7c0f Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 14 Jan 2024 19:26:23 -0800 Subject: [PATCH 149/195] [temp][linter fixup] Add dummy C++ unit test --- .../tests/SessionOptionsScenario.java | 76 +++++++++---------- 1 file changed, 35 insertions(+), 41 deletions(-) diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index d85584fb35768..85e8ff9f22689 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; +import com.google.common.collect.ImmutableMap; import org.apache.arrow.flight.CloseSessionRequest; import org.apache.arrow.flight.CloseSessionResult; import org.apache.arrow.flight.FlightClient; @@ -68,53 +69,46 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig () -> client.getSessionOptions(new GetSessionOptionsRequest())); // Set - SetSessionOptionsRequest req1 = new SetSessionOptionsRequest(new HashMap() { - { - put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)); - put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)); - put("lol_invalid", SessionOptionValueFactory.makeSessionOptionValue("this won't get set")); - put("key_with_invalid_value", SessionOptionValueFactory.makeSessionOptionValue("lol_invalid")); - put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( - new String[]{"a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"})); - } - }); + SetSessionOptionsRequest req1 = new SetSessionOptionsRequest(ImmutableMap.builder() + .put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)) + .put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)) + .put("lol_invalid", SessionOptionValueFactory.makeSessionOptionValue("this won't get set")) + .put("key_with_invalid_value", SessionOptionValueFactory.makeSessionOptionValue("lol_invalid")) + .put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( + new String[]{"a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"})) + .build()); SetSessionOptionsResult res1 = client.setSessionOptions(req1); // Some errors - IntegrationAssertions.assertEquals(new HashMap() { - { - put("lol_invalid", new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)); - put("key_with_invalid_value", new SetSessionOptionsResult.Error( - SetSessionOptionsResult.ErrorValue.INVALID_VALUE)); - } - }, res1.getErrors()); + IntegrationAssertions.assertEquals(ImmutableMap.builder() + .put("lol_invalid", new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)) + .put("key_with_invalid_value", new SetSessionOptionsResult.Error( + SetSessionOptionsResult.ErrorValue.INVALID_VALUE)) + .build(), + res1.getErrors()); // Some set, some omitted due to errors GetSessionOptionsResult res2 = client.getSessionOptions(new GetSessionOptionsRequest()); - IntegrationAssertions.assertEquals(new HashMap() { - { - put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)); - put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)); - put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( - new String[]{"a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"})); - } - }, res2.getSessionOptions()); + IntegrationAssertions.assertEquals(ImmutableMap.builder() + .put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)) + .put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)) + .put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( + new String[]{"a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"})) + .build(), + res2.getSessionOptions()); // Update - client.setSessionOptions(new SetSessionOptionsRequest(new HashMap() { - { - // Delete - put("foolong", SessionOptionValueFactory.makeEmptySessionOptionValue()); - // Update - put("big_ol_string_list", - SessionOptionValueFactory.makeSessionOptionValue("a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ")); - } - })); + client.setSessionOptions(new SetSessionOptionsRequest(ImmutableMap.builder() + // Delete + .put("foolong", SessionOptionValueFactory.makeEmptySessionOptionValue()) + // Update + .put("big_ol_string_list", + SessionOptionValueFactory.makeSessionOptionValue("a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ")) + .build())); GetSessionOptionsResult res4 = client.getSessionOptions(new GetSessionOptionsRequest()); - IntegrationAssertions.assertEquals(new HashMap() { - { - put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)); - put("big_ol_string_list", - SessionOptionValueFactory.makeSessionOptionValue("a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ")); - } - }, res4.getSessionOptions()); + IntegrationAssertions.assertEquals(ImmutableMap.builder() + .put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)) + .put("big_ol_string_list", + SessionOptionValueFactory.makeSessionOptionValue("a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ")) + .build(), + res4.getSessionOptions()); // Close CloseSessionResult res5 = client.closeSession(new CloseSessionRequest()); IntegrationAssertions.assertEquals(CloseSessionResult.Status.CLOSED, res5.getStatus()); From c7f7dec2dff8cc12a0fd3ae56c5920f156585ffc Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 15 Jan 2024 13:22:09 -0800 Subject: [PATCH 150/195] Fix Java build errors & dependencies --- java/flight/flight-integration-tests/pom.xml | 4 ++++ .../flight/integration/tests/SessionOptionsScenario.java | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/java/flight/flight-integration-tests/pom.xml b/java/flight/flight-integration-tests/pom.xml index 944c624d630a2..2a7cec9a1306b 100644 --- a/java/flight/flight-integration-tests/pom.xml +++ b/java/flight/flight-integration-tests/pom.xml @@ -45,6 +45,10 @@ com.google.protobuf protobuf-java + + com.google.guava + guava + commons-cli commons-cli diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index 85e8ff9f22689..d86aee8279db2 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; -import com.google.common.collect.ImmutableMap; import org.apache.arrow.flight.CloseSessionRequest; import org.apache.arrow.flight.CloseSessionResult; import org.apache.arrow.flight.FlightClient; @@ -40,6 +39,8 @@ import org.apache.arrow.flight.sql.FlightSqlClient; import org.apache.arrow.memory.BufferAllocator; +import com.google.common.collect.ImmutableMap; + /** * Scenario to exercise Session Options functionality. */ @@ -79,7 +80,7 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig .build()); SetSessionOptionsResult res1 = client.setSessionOptions(req1); // Some errors - IntegrationAssertions.assertEquals(ImmutableMap.builder() + IntegrationAssertions.assertEquals(ImmutableMap.builder() .put("lol_invalid", new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)) .put("key_with_invalid_value", new SetSessionOptionsResult.Error( SetSessionOptionsResult.ErrorValue.INVALID_VALUE)) From a200fea7cb044d3750531ae20aceaf244c4b4602 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 15 Jan 2024 19:47:29 -0800 Subject: [PATCH 151/195] [Java builds][C++ builds] Extricate int32 & float --- .../arrow/flight/serialization_internal.cc | 8 -- cpp/src/arrow/flight/types.h | 4 +- format/Flight.proto | 8 +- .../arrow/flight/SessionOptionValue.java | 12 --- .../flight/SessionOptionValueFactory.java | 82 ------------------- .../flight/SessionOptionValueVisitor.java | 10 --- .../tests/SessionOptionsScenario.java | 6 +- 7 files changed, 8 insertions(+), 122 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 796199a88e8c9..607faeee77eed 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -401,15 +401,9 @@ Status FromProto(const pb::SessionOptionValue& pb_val, SessionOptionValue* val) case pb::SessionOptionValue::kBoolValue: *val = pb_val.bool_value(); break; - case pb::SessionOptionValue::kInt32Value: - *val = pb_val.int32_value(); - break; case pb::SessionOptionValue::kInt64Value: *val = pb_val.int64_value(); break; - case pb::SessionOptionValue::kFloatValue: - *val = pb_val.float_value(); - break; case pb::SessionOptionValue::kDoubleValue: *val = pb_val.double_value(); break; @@ -430,9 +424,7 @@ Status ToProto(const SessionOptionValue& val, pb::SessionOptionValue* pb_val) { std::visit(overloaded{[&](std::monostate v) { pb_val->clear_option_value(); }, [&](std::string v) { pb_val->set_string_value(v); }, [&](bool v) { pb_val->set_bool_value(v); }, - [&](int32_t v) { pb_val->set_int32_value(v); }, [&](int64_t v) { pb_val->set_int64_value(v); }, - [&](float v) { pb_val->set_float_value(v); }, [&](double v) { pb_val->set_double_value(v); }, [&](std::vector v) { auto* string_list_value = pb_val->mutable_string_list_value(); diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index a7b2cd954f82b..13bf69a998306 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -769,8 +769,8 @@ struct ARROW_FLIGHT_EXPORT CancelFlightInfoRequest { /// /// By convention, an attempt to set a valueless (std::monostate) SessionOptionValue /// should attempt to unset or clear the named option value on the server. -using SessionOptionValue = std::variant>; +using SessionOptionValue = std::variant>; /// \brief The result of setting a session option. enum class SetSessionOptionErrorValue : int8_t { diff --git a/format/Flight.proto b/format/Flight.proto index 3841cd0787c57..e8c96db5765f7 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -540,11 +540,9 @@ message SessionOptionValue { oneof option_value { string string_value = 1; bool bool_value = 2; - sfixed32 int32_value = 3; - sfixed64 int64_value = 4; - float float_value = 5; - double double_value = 6; - StringListValue string_list_value = 7; + sfixed64 int64_value = 3; + double double_value = 4; + StringListValue string_list_value = 5; } } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index 4c1c54d7ce4e1..af0fb92783e27 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -61,24 +61,12 @@ public Void visit(boolean value) { return null; } - @Override - public Void visit(int value) { - b.setInt32Value(value); - return null; - } - @Override public Void visit(long value) { b.setInt64Value(value); return null; } - @Override - public Void visit(float value) { - b.setFloatValue(value); - return null; - } - @Override public Void visit(double value) { b.setDoubleValue(value); diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java index 7edb7a7e55ee9..47c82fa7bb7fd 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueFactory.java @@ -32,18 +32,10 @@ public static SessionOptionValue makeSessionOptionValue(boolean value) { return new SessionOptionValueBoolean(value); } - public static SessionOptionValue makeSessionOptionValue(int value) { - return new SessionOptionValueInt(value); - } - public static SessionOptionValue makeSessionOptionValue(long value) { return new SessionOptionValueLong(value); } - public static SessionOptionValue makeSessionOptionValue(float value) { - return new SessionOptionValueFloat(value); - } - public static SessionOptionValue makeSessionOptionValue(double value) { return new SessionOptionValueDouble(value); } @@ -63,12 +55,8 @@ public static SessionOptionValue makeSessionOptionValue(Flight.SessionOptionValu return new SessionOptionValueString(proto.getStringValue()); case BOOL_VALUE: return new SessionOptionValueBoolean(proto.getBoolValue()); - case INT32_VALUE: - return new SessionOptionValueInt(proto.getInt32Value()); case INT64_VALUE: return new SessionOptionValueLong(proto.getInt64Value()); - case FLOAT_VALUE: - return new SessionOptionValueFloat(proto.getFloatValue()); case DOUBLE_VALUE: return new SessionOptionValueDouble(proto.getDoubleValue()); case STRING_LIST_VALUE: @@ -153,41 +141,6 @@ public String toString() { } } - private static class SessionOptionValueInt extends SessionOptionValue { - private final int value; - - SessionOptionValueInt(int value) { - this.value = value; - } - - @Override - public T acceptVisitor(SessionOptionValueVisitor v) { - return v.visit(value); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SessionOptionValueInt that = (SessionOptionValueInt) o; - return value == that.value; - } - - @Override - public int hashCode() { - return Integer.hashCode(value); - } - - @Override - public String toString() { - return String.valueOf(value); - } - } - private static class SessionOptionValueLong extends SessionOptionValue { private final long value; @@ -223,41 +176,6 @@ public String toString() { } } - private static class SessionOptionValueFloat extends SessionOptionValue { - private final float value; - - SessionOptionValueFloat(Float value) { - this.value = value; - } - - @Override - public T acceptVisitor(SessionOptionValueVisitor v) { - return v.visit(value); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - SessionOptionValueFloat that = (SessionOptionValueFloat) o; - return value == that.value; - } - - @Override - public int hashCode() { - return Float.hashCode(value); - } - - @Override - public String toString() { - return String.valueOf(value); - } - } - private static class SessionOptionValueDouble extends SessionOptionValue { private final double value; diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java index 30feddb4bd2f6..f2178224a0d29 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValueVisitor.java @@ -33,21 +33,11 @@ public interface SessionOptionValueVisitor { */ T visit(boolean value); - /** - * A callback to handle SessionOptionValue containing an int. - */ - T visit(int value); - /** * A callback to handle SessionOptionValue containing a long. */ T visit(long value); - /** - * A callback to handle SessionOptionValue containing a float. - */ - T visit(float value); - /** * A callback to handle SessionOptionValue containing a double. */ diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index d86aee8279db2..2618e217a28c6 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -72,7 +72,7 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig // Set SetSessionOptionsRequest req1 = new SetSessionOptionsRequest(ImmutableMap.builder() .put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)) - .put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)) + .put("bardouble", SessionOptionValueFactory.makeSessionOptionValue(456.0)) .put("lol_invalid", SessionOptionValueFactory.makeSessionOptionValue("this won't get set")) .put("key_with_invalid_value", SessionOptionValueFactory.makeSessionOptionValue("lol_invalid")) .put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( @@ -90,7 +90,7 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig GetSessionOptionsResult res2 = client.getSessionOptions(new GetSessionOptionsRequest()); IntegrationAssertions.assertEquals(ImmutableMap.builder() .put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)) - .put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)) + .put("bardouble", SessionOptionValueFactory.makeSessionOptionValue(456.0)) .put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue( new String[]{"a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"})) .build(), @@ -105,7 +105,7 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig .build())); GetSessionOptionsResult res4 = client.getSessionOptions(new GetSessionOptionsRequest()); IntegrationAssertions.assertEquals(ImmutableMap.builder() - .put("barfloat", SessionOptionValueFactory.makeSessionOptionValue(456.0f)) + .put("bardouble", SessionOptionValueFactory.makeSessionOptionValue(456.0)) .put("big_ol_string_list", SessionOptionValueFactory.makeSessionOptionValue("a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ")) .build(), From 62bc378693a773b0683e37b9789d7f19a5f2659b Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 15 Jan 2024 19:48:10 -0800 Subject: [PATCH 152/195] [Java builds][C++ builds] Add NoOpSessionOptionValueVisitor --- .../flight/NoOpSessionOptionValueVisitor.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 java/flight/flight-core/src/main/java/org/apache/arrow/flight/NoOpSessionOptionValueVisitor.java diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/NoOpSessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/NoOpSessionOptionValueVisitor.java new file mode 100644 index 0000000000000..bf2abdda13428 --- /dev/null +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/NoOpSessionOptionValueVisitor.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.arrow.flight; + +/** + * A helper to facilitate easier anonymous subclass declaration. + * + * Implementations need only override callbacks for types they wish to do something with. + */ +public class NoOpSessionOptionValueVisitor implements SessionOptionValueVisitor { + /** + * A callback to handle SessionOptionValue containing a String. + */ + public Object visit(String value) { + return null; + } + + /** + * A callback to handle SessionOptionValue containing a boolean. + */ + public Object visit(boolean value) { + return null; + } + + /** + * A callback to handle SessionOptionValue containing a long. + */ + public Object visit(long value) { + return null; + } + + /** + * A callback to handle SessionOptionValue containing a double. + */ + public Object visit(double value) { + return null; + } + + /** + * A callback to handle SessionOptionValue containing an array of String. + */ + public Object visit(String[] value) { + return null; + } + + /** + * A callback to handle SessionOptionValue containing no value. + * + * By convention, an attempt to set a valueless SessionOptionValue should + * attempt to unset or clear the named option value on the server. + */ + public Object visit(Void value) { + return null; + } +} From 82bc842ab041bd8fb0901e85dad2cd667743f6c6 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 16 Jan 2024 10:11:28 -0800 Subject: [PATCH 153/195] Test adding Flight C++ unit test --- cpp/src/arrow/flight/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpp/src/arrow/flight/CMakeLists.txt b/cpp/src/arrow/flight/CMakeLists.txt index 91e0fbf9136d3..e995c114d58e2 100644 --- a/cpp/src/arrow/flight/CMakeLists.txt +++ b/cpp/src/arrow/flight/CMakeLists.txt @@ -291,6 +291,12 @@ add_arrow_test(flight_test LABELS "arrow_flight") +add_arrow_test(server_session_middleware_internals_test + STATIC_LINK_LIBS + ${ARROW_FLIGHT_TEST_LINK_LIBS} + LABELS + "arrow_flight") + # Build test server for unit tests or benchmarks if(ARROW_BUILD_TESTS OR ARROW_BUILD_BENCHMARKS) add_executable(flight-test-server test_server.cc) From 1e45e449cdab775c1ed658f19b3ac467bd336f4d Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 16 Jan 2024 11:04:46 -0800 Subject: [PATCH 154/195] Test #2 adding Flight C++ unit test --- cpp/src/arrow/flight/CMakeLists.txt | 6 ------ cpp/src/arrow/flight/sql/CMakeLists.txt | 6 +++++- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/cpp/src/arrow/flight/CMakeLists.txt b/cpp/src/arrow/flight/CMakeLists.txt index e995c114d58e2..91e0fbf9136d3 100644 --- a/cpp/src/arrow/flight/CMakeLists.txt +++ b/cpp/src/arrow/flight/CMakeLists.txt @@ -291,12 +291,6 @@ add_arrow_test(flight_test LABELS "arrow_flight") -add_arrow_test(server_session_middleware_internals_test - STATIC_LINK_LIBS - ${ARROW_FLIGHT_TEST_LINK_LIBS} - LABELS - "arrow_flight") - # Build test server for unit tests or benchmarks if(ARROW_BUILD_TESTS OR ARROW_BUILD_BENCHMARKS) add_executable(flight-test-server test_server.cc) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index 6c31db10b204b..2d17adcba08b6 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -105,7 +105,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) example/sqlite_server.cc example/sqlite_tables_schema_batch_reader.cc) - set(ARROW_FLIGHT_SQL_TEST_SRCS server_test.cc) + set(ARROW_FLIGHT_SQL_TEST_SRCS server_test.cc server_session_middleware_internals_test.cc) set(ARROW_FLIGHT_SQL_TEST_LIBS ${SQLite3_LIBRARIES}) set(ARROW_FLIGHT_SQL_ACERO_SRCS example/acero_server.cc) @@ -140,6 +140,10 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) LABELS "arrow_flight_sql") + add_arrow_test(flight_sql_server_session_middleware_internals + SOURCES + ) + add_executable(flight-sql-test-server test_server_cli.cc ${ARROW_FLIGHT_SQL_TEST_SERVER_SRCS}) target_link_libraries(flight-sql-test-server From 9630c13fe0a4365302eab064a797ab5b284bf687 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 16 Jan 2024 11:26:06 -0800 Subject: [PATCH 155/195] Test #3 adding Flight C++ unit test --- cpp/src/arrow/flight/sql/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index 2d17adcba08b6..bf09fa40cfc5d 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -140,10 +140,6 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) LABELS "arrow_flight_sql") - add_arrow_test(flight_sql_server_session_middleware_internals - SOURCES - ) - add_executable(flight-sql-test-server test_server_cli.cc ${ARROW_FLIGHT_SQL_TEST_SERVER_SRCS}) target_link_libraries(flight-sql-test-server From 59001cfd508d5366497a4cc34e23647263163015 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 16 Jan 2024 11:45:00 -0800 Subject: [PATCH 156/195] Test #4 adding Flight C++ unit test --- cpp/src/arrow/flight/sql/server_session_middleware_factory.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h index 4e3d72676f51e..d6c7c68630e11 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h @@ -26,6 +26,8 @@ #include #include +#include + namespace arrow { namespace flight { namespace sql { From 24efb90fad9521514f9e7c5f8e5549792849fa36 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 16 Jan 2024 12:21:47 -0800 Subject: [PATCH 157/195] Test #5 adding Flight C++ unit test --- .../flight/sql/server_session_middleware_internals_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc index 93f162e280318..4d6aa673022a7 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc @@ -29,7 +29,7 @@ namespace sql { class ServerSessionMiddlewareFactoryPrivate : public ServerSessionMiddlewareFactory { public: using ServerSessionMiddlewareFactory::ParseCookieString; -} +}; TEST(ServerSessionMiddleware, Dummy) { ASSERT_EQ(1, 1); From e69c7ecf3c13cfd723ada7cd7f77563c7f574bb9 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 16 Jan 2024 13:30:17 -0800 Subject: [PATCH 158/195] [C++ builds] added tautological failure to arrow-flight-sql-test --- .../flight/sql/server_session_middleware_internals_test.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc index 4d6aa673022a7..ed9c79f5e7084 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc @@ -18,6 +18,8 @@ // ---------------------------------------------------------------------- // ServerSessionMiddleware{,Factory} tests not involing a client/server instance +#include + #include #include @@ -32,7 +34,7 @@ class ServerSessionMiddlewareFactoryPrivate : public ServerSessionMiddlewareFact }; TEST(ServerSessionMiddleware, Dummy) { - ASSERT_EQ(1, 1); + ASSERT_EQ(1, 0); } } // namespace sql From 9e4879310f1dbf039baaea19e78cfab6462378d6 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 16 Jan 2024 17:28:36 -0800 Subject: [PATCH 159/195] [C++ builds] Add C++ ServerSessionMiddleware cookie parsing test --- .../arrow/flight/sql/server_session_middleware.cc | 15 +++++++++++++-- .../sql/server_session_middleware_factory.h | 2 +- .../server_session_middleware_internals_test.cc | 11 +++++++---- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index a492b2ab63e91..07949964fa84d 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -92,8 +92,19 @@ ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { // The cookie header is somewhat malformed; ignore the key and continue parsing continue; } - result.emplace_back(tok.substr(0, val_pos), - tok.substr(val_pos + pair_sep.length(), std::string::npos)); + const std::string_view cookie_name = tok.substr(0, val_pos); + std::string_view cookie_value = tok.substr(val_pos + pair_sep.length(), std::string::npos); + if (cookie_name.empty()) { + continue; + } + // Strip doublequotes + if (cookie_value.length() >= 2 && + cookie_value.front() == '"' && + cookie_value.back() == '"') { + cookie_value.remove_prefix(1); + cookie_value.remove_suffix(1); + } + result.emplace_back(cookie_name, cookie_value); } return result; diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h index d6c7c68630e11..f6522efb644b0 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h @@ -39,7 +39,7 @@ class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { std::shared_mutex session_store_lock_; std::function id_generator_; - std::vector> ParseCookieString( + static std::vector> ParseCookieString( const std::string_view& s); public: diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc index ed9c79f5e7084..840a469f0a7bc 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc @@ -18,8 +18,6 @@ // ---------------------------------------------------------------------- // ServerSessionMiddleware{,Factory} tests not involing a client/server instance -#include - #include #include @@ -33,8 +31,13 @@ class ServerSessionMiddlewareFactoryPrivate : public ServerSessionMiddlewareFact using ServerSessionMiddlewareFactory::ParseCookieString; }; -TEST(ServerSessionMiddleware, Dummy) { - ASSERT_EQ(1, 0); +TEST(ServerSessionMiddleware, ParseCookieString) { + std::vector> r1 = + ServerSessionMiddlewareFactoryPrivate::ParseCookieString( + "k1=v1; k2=\"v2\"; kempty=; k3=v3"); + std::vector> e1 = + {{"k1", "v1"}, {"k2", "v2"}, {"kempty", ""}, {"k3", "v3"}}; + ASSERT_EQ(e1, r1); } } // namespace sql From b68800d387468e8e1e5621f0f1bfda7fba2d7d05 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 19 Jan 2024 14:13:20 -0800 Subject: [PATCH 160/195] [C++ builds] Probably fix Win64 C++ CI build linker error --- cpp/src/arrow/flight/sql/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index bf09fa40cfc5d..edd17dd9129c6 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -105,7 +105,10 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) example/sqlite_server.cc example/sqlite_tables_schema_batch_reader.cc) - set(ARROW_FLIGHT_SQL_TEST_SRCS server_test.cc server_session_middleware_internals_test.cc) + set(ARROW_FLIGHT_SQL_TEST_SRCS + server_test.cc + server_session_middleware.cc + server_session_middleware_internals_test.cc) set(ARROW_FLIGHT_SQL_TEST_LIBS ${SQLite3_LIBRARIES}) set(ARROW_FLIGHT_SQL_ACERO_SRCS example/acero_server.cc) From 6cd8ce6df822d5d9d7ba83093947fa02657ae1ce Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 19 Jan 2024 15:14:53 -0800 Subject: [PATCH 161/195] Revert "[C++ builds] Probably fix Win64 C++ CI build linker error" This reverts commit 1eff105b79729fb711fba292c6439420b9324c54. --- cpp/src/arrow/flight/sql/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index edd17dd9129c6..bf09fa40cfc5d 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -105,10 +105,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) example/sqlite_server.cc example/sqlite_tables_schema_batch_reader.cc) - set(ARROW_FLIGHT_SQL_TEST_SRCS - server_test.cc - server_session_middleware.cc - server_session_middleware_internals_test.cc) + set(ARROW_FLIGHT_SQL_TEST_SRCS server_test.cc server_session_middleware_internals_test.cc) set(ARROW_FLIGHT_SQL_TEST_LIBS ${SQLite3_LIBRARIES}) set(ARROW_FLIGHT_SQL_ACERO_SRCS example/acero_server.cc) From dbce9ceed78b65231baf511e3499803b9e70ed72 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 19 Jan 2024 16:11:28 -0800 Subject: [PATCH 162/195] [C++ builds] CI linter fixups --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 6 +++--- .../flight/sql/server_session_middleware_internals_test.cc | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 07949964fa84d..958f7132834f8 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -93,13 +93,13 @@ ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { continue; } const std::string_view cookie_name = tok.substr(0, val_pos); - std::string_view cookie_value = tok.substr(val_pos + pair_sep.length(), std::string::npos); + std::string_view cookie_value = + tok.substr(val_pos + pair_sep.length(), std::string::npos); if (cookie_name.empty()) { continue; } // Strip doublequotes - if (cookie_value.length() >= 2 && - cookie_value.front() == '"' && + if (cookie_value.length() >= 2 && cookie_value.front() == '"' && cookie_value.back() == '"') { cookie_value.remove_prefix(1); cookie_value.remove_suffix(1); diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc index 840a469f0a7bc..74e4d7845c699 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware_internals_test.cc @@ -34,9 +34,9 @@ class ServerSessionMiddlewareFactoryPrivate : public ServerSessionMiddlewareFact TEST(ServerSessionMiddleware, ParseCookieString) { std::vector> r1 = ServerSessionMiddlewareFactoryPrivate::ParseCookieString( - "k1=v1; k2=\"v2\"; kempty=; k3=v3"); - std::vector> e1 = - {{"k1", "v1"}, {"k2", "v2"}, {"kempty", ""}, {"k3", "v3"}}; + "k1=v1; k2=\"v2\"; kempty=; k3=v3"); + std::vector> e1 = { + {"k1", "v1"}, {"k2", "v2"}, {"kempty", ""}, {"k3", "v3"}}; ASSERT_EQ(e1, r1); } From f11e997ecaf28b350fb676fbbffb369758f24bb4 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 19 Jan 2024 19:01:48 -0800 Subject: [PATCH 163/195] [C++ builds] Linter + linker fixups --- cpp/src/arrow/flight/sql/CMakeLists.txt | 4 +++- cpp/src/arrow/flight/sql/server_session_middleware_factory.h | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index bf09fa40cfc5d..7da5ec22afcb9 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -105,7 +105,9 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) example/sqlite_server.cc example/sqlite_tables_schema_batch_reader.cc) - set(ARROW_FLIGHT_SQL_TEST_SRCS server_test.cc server_session_middleware_internals_test.cc) + set(ARROW_FLIGHT_SQL_TEST_SRCS + server_test.cc + server_session_middleware_internals_test.cc) set(ARROW_FLIGHT_SQL_TEST_LIBS ${SQLite3_LIBRARIES}) set(ARROW_FLIGHT_SQL_ACERO_SRCS example/acero_server.cc) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h index f6522efb644b0..bdd0f60748045 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h @@ -33,7 +33,8 @@ namespace flight { namespace sql { /// \brief A factory for ServerSessionMiddleware, itself storing session data. -class ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { +class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddlewareFactory + : public ServerMiddlewareFactory { protected: std::map> session_store_; std::shared_mutex session_store_lock_; From ec26615352e27b1c671f7c29c68ee2a5c7a7c472 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 19 Jan 2024 19:04:05 -0800 Subject: [PATCH 164/195] [Docs] Doc fixup --- cpp/src/arrow/flight/types.h | 2 +- format/Flight.proto | 2 +- .../java/org/apache/arrow/flight/SetSessionOptionsResult.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/types.h b/cpp/src/arrow/flight/types.h index 13bf69a998306..4b17149aa2d46 100644 --- a/cpp/src/arrow/flight/types.h +++ b/cpp/src/arrow/flight/types.h @@ -781,7 +781,7 @@ enum class SetSessionOptionErrorValue : int8_t { kUnspecified, /// \brief The given session option name is invalid. kInvalidName, - /// \brief The session option value is invalid. + /// \brief The session option value or type is invalid. kInvalidValue, /// \brief The session option cannot be set. kError diff --git a/format/Flight.proto b/format/Flight.proto index e8c96db5765f7..f14699f24b083 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -572,7 +572,7 @@ message SetSessionOptionsResult { UNSPECIFIED = 0; // The given session option name is invalid. INVALID_NAME = 1; - // The session option value is invalid. + // The session option value or type is invalid. INVALID_VALUE = 2; // The session option cannot be set. ERROR = 3; diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java index b250375e39228..14d53cc6767e0 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SetSessionOptionsResult.java @@ -41,7 +41,7 @@ public enum ErrorValue { */ INVALID_NAME, /** - * The session option value is invalid. + * The session option value or type is invalid. */ INVALID_VALUE, /** From 565a79c6a800755bb33a8bda087307afa612479b Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 21 Jan 2024 01:00:41 -0800 Subject: [PATCH 165/195] [C++ builds][Java builds] PR feedback etc --- .../sql/server_session_middleware_factory.h | 2 +- format/Flight.proto | 9 ++++++++- .../arrow/flight/CloseSessionRequest.java | 3 +-- .../arrow/flight/GetSessionOptionsRequest.java | 3 +-- .../arrow/flight/ServerSessionMiddleware.java | 17 ++++++++--------- .../apache/arrow/flight/SessionOptionValue.java | 2 ++ java/flight/flight-integration-tests/pom.xml | 8 ++++---- .../flight/sql/CloseSessionResultListener.java | 2 +- .../sql/GetSessionOptionsResultListener.java | 2 +- .../sql/SetSessionOptionsResultListener.java | 2 +- 10 files changed, 28 insertions(+), 22 deletions(-) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h index bdd0f60748045..56becf56e0c1f 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h @@ -47,7 +47,7 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddlewareFactory explicit ServerSessionMiddlewareFactory(std::function id_gen) : id_generator_(id_gen) {} Status StartCall(const CallInfo&, const CallHeaders& incoming_headers, - std::shared_ptr* middleware); + std::shared_ptr* middleware) override; /// \brief Get a new, empty session option map and its id key. std::pair> CreateNewSession(); diff --git a/format/Flight.proto b/format/Flight.proto index f14699f24b083..d0a661ae8bd4a 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -554,6 +554,11 @@ message SessionOptionValue { * RFC 6265 HTTP cookies when using an HTTP transport. The suggested cookie name or state * context key is 'arrow_flight_session_id', although implementations may freely choose their * own name. + * + * Session creation (if one does not already exist) is implied by this RPC request, however + * server implementations may choose to initiate a session that also contains client-provided + * session options at any other time, e.g. on authentication, or when any other call is made + * and the server wishes to use a session to persist any state (or lack thereof). */ message SetSessionOptionsRequest { map session_options = 1; @@ -562,7 +567,9 @@ message SetSessionOptionsRequest { /* * EXPERIMENTAL: The results (individually) of setting a set of session options. * - * Option names should only be present in the + * Option names should only be present in the response if they were not successfully + * set on the server; that is, a response without an Error for a key provided in the + * SetSessionOptionsRequest implies that the named option value was set successfully. */ message SetSessionOptionsResult { enum ErrorValue { diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java index 77a5a2d8be618..e700b73e652bc 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java @@ -29,8 +29,7 @@ public CloseSessionRequest() {} CloseSessionRequest(Flight.CloseSessionRequest proto) {} Flight.CloseSessionRequest toProtocol() { - Flight.CloseSessionRequest.Builder b = Flight.CloseSessionRequest.newBuilder(); - return b.build(); + return Flight.CloseSessionRequest.getDefaultInstance(); } /** diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java index 1609d8520b20f..4c40260d50044 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java @@ -31,8 +31,7 @@ public GetSessionOptionsRequest() {} GetSessionOptionsRequest(Flight.GetSessionOptionsRequest proto) {} Flight.GetSessionOptionsRequest toProtocol() { - Flight.GetSessionOptionsRequest.Builder b = Flight.GetSessionOptionsRequest.newBuilder(); - return b.build(); + return Flight.GetSessionOptionsRequest.getDefaultInstance(); } /** diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java index 1f599ca99b07b..7091caa5e98bc 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/ServerSessionMiddleware.java @@ -22,6 +22,7 @@ import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** * Middleware for handling Flight SQL Sessions including session cookie handling. @@ -40,7 +41,7 @@ public class ServerSessionMiddleware implements FlightServerMiddleware { * Factory for managing and accessing ServerSessionMiddleware. */ public static class Factory implements FlightServerMiddleware.Factory { - private final Map sessionStore = + private final ConcurrentMap sessionStore = new ConcurrentHashMap<>(); private final Callable idGenerator; @@ -61,16 +62,14 @@ private synchronized Session createNewSession() { id = idGenerator.call(); } catch (Exception ignored) { // Most impls aren't going to throw so don't make caller handle a nonexistent checked exception - return null; - } - if (sessionStore.containsKey(id)) { - // Collision, should also never happen - return null; + throw CallStatus.INTERNAL.withDescription("Session creation error").toRuntimeException(); } Session newSession = new Session(id); - sessionStore.put(id, newSession); - + if (sessionStore.putIfAbsent(id, newSession) != null) { + // Collision, should never happen + throw CallStatus.INTERNAL.withDescription("Session creation error").toRuntimeException(); + } return newSession; } @@ -125,7 +124,7 @@ public ServerSessionMiddleware onCallStarted(CallInfo callInfo, CallHeaders inco */ public static class Session { public final String id; - private Map sessionData = + private ConcurrentMap sessionData = new ConcurrentHashMap(); /** diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index af0fb92783e27..bc4aecc352030 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -25,6 +25,8 @@ * A union-like container interface for supported session option value types. */ public abstract class SessionOptionValue { + SessionOptionValue() {} + /** * Value access via a caller-provided visitor/functor. */ diff --git a/java/flight/flight-integration-tests/pom.xml b/java/flight/flight-integration-tests/pom.xml index 2a7cec9a1306b..905c8bdaf013b 100644 --- a/java/flight/flight-integration-tests/pom.xml +++ b/java/flight/flight-integration-tests/pom.xml @@ -45,10 +45,10 @@ com.google.protobuf protobuf-java - - com.google.guava - guava - + + com.google.guava + guava + commons-cli commons-cli diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java index 5ebfa0becc106..e1a5b369fe16c 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/CloseSessionResultListener.java @@ -21,7 +21,7 @@ import org.apache.arrow.flight.FlightProducer; import org.apache.arrow.flight.Result; -/** Typed StreamListener for renewFlightEndpoint. */ +/** Typed StreamListener for closeSession. */ public class CloseSessionResultListener implements FlightProducer.StreamListener { private final FlightProducer.StreamListener listener; diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java index 214a98464db71..4fdffd076243c 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/GetSessionOptionsResultListener.java @@ -21,7 +21,7 @@ import org.apache.arrow.flight.GetSessionOptionsResult; import org.apache.arrow.flight.Result; -/** Typed StreamListener for renewFlightEndpoint. */ +/** Typed StreamListener for getSessionOptions. */ public class GetSessionOptionsResultListener implements FlightProducer.StreamListener { private final FlightProducer.StreamListener listener; diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java index a13e1694c5fbc..230be2bf1b316 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/SetSessionOptionsResultListener.java @@ -21,7 +21,7 @@ import org.apache.arrow.flight.Result; import org.apache.arrow.flight.SetSessionOptionsResult; -/** Typed StreamListener for renewFlightEndpoint. */ +/** Typed StreamListener for setSessionOptions. */ public class SetSessionOptionsResultListener implements FlightProducer.StreamListener { private final FlightProducer.StreamListener listener; From 82be14d83e3a65676e70fa6e80aac98b0236c425 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 21 Jan 2024 01:26:43 -0800 Subject: [PATCH 166/195] Guessed workaround for opaque CMake linter error --- cpp/src/arrow/flight/sql/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index 7da5ec22afcb9..f08614a3c532e 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -108,6 +108,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) set(ARROW_FLIGHT_SQL_TEST_SRCS server_test.cc server_session_middleware_internals_test.cc) + set(ARROW_FLIGHT_SQL_TEST_LIBS ${SQLite3_LIBRARIES}) set(ARROW_FLIGHT_SQL_ACERO_SRCS example/acero_server.cc) From 6d27c34213362af4c0e24c42aea6c4aecd622ad3 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 21 Jan 2024 01:53:53 -0800 Subject: [PATCH 167/195] Remove extraneous whitespace in CMakeLists.txt --- cpp/src/arrow/flight/sql/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index f08614a3c532e..3cf0bd17fe4a4 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -108,7 +108,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) set(ARROW_FLIGHT_SQL_TEST_SRCS server_test.cc server_session_middleware_internals_test.cc) - + set(ARROW_FLIGHT_SQL_TEST_LIBS ${SQLite3_LIBRARIES}) set(ARROW_FLIGHT_SQL_ACERO_SRCS example/acero_server.cc) From 39e21a7b5b4f3597beddba4900eda0c8699a3d3c Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 21 Jan 2024 18:45:03 -0800 Subject: [PATCH 168/195] [C++ builds] checkpoint --- .../integration_tests/test_integration.cc | 133 +++++++++++++++++- .../flight/sql/server_session_middleware.cc | 41 ++++-- .../flight/sql/server_session_middleware.h | 10 +- .../sql/server_session_middleware_factory.h | 7 +- .../tests/SessionOptionsProducer.java | 4 +- 5 files changed, 179 insertions(+), 16 deletions(-) diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index b693662f60740..d97178701fabc 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -33,6 +33,7 @@ #include "arrow/flight/sql/client.h" #include "arrow/flight/sql/column_metadata.h" #include "arrow/flight/sql/server.h" +#include "arrow/flight/sql/server_session_middleware.h" #include "arrow/flight/sql/types.h" #include "arrow/flight/test_util.h" #include "arrow/flight/types.h" @@ -716,7 +717,7 @@ class ExpirationTimeRenewFlightEndpointScenario : public Scenario { return Status::OK(); } - Status MakeClient(FlightClientOptions* options) override { return Status::OK(); } + Status MakeClient(FlightClientOptions* options) override {return Status::OK(); } Status RunClient(std::unique_ptr client) override { ARROW_ASSIGN_OR_RAISE(auto info, @@ -744,6 +745,136 @@ class ExpirationTimeRenewFlightEndpointScenario : public Scenario { } }; + + + +// FIXME PHOXME whitespace and after class + +/// \brief The server used for testing Session Options. +/// +/// setSessionOptions has a blacklisted option name and string option value, +/// both "lol_invalid", which will result in errors attempting to set either. +class SessionOptionsServer : public sql::FlightSqlServerBase { + inline const static std::string invalid_option_name = "lol_invalid"; + inline const static SessionOptionValue invalid_option_value = "lol_invalid"; + + const std::string session_middleware_key; + // These will never be threaded so using a plain map and no lock + std::map session_store_; + + public: + // FIXME PHOXME need to handle middleware lookup token wherever + SessionOptionsServer(std::string session_middleware_key) + : FlightSqlServerBase(), + session_middleware_key(std::move(session_middleware_key)) { + + } + + arrow::Result SetSessionOptions( + const ServerCallContext& context, + const SetSessionOptionsRequest& request) override { + SetSessionOptionsResult res; + + sql::ServerSessionMiddleware* middleware = + (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + std::shared_ptr session = middleware->GetSession(); + + for (const auto& [name, value] : request.session_options) { + // Blacklisted value name + if (name == invalid_option_name) { + res.errors.emplace(name, SetSessionOptionsResult::Error{ + SetSessionOptionErrorValue::kInvalidName}); + continue; + } + // Blacklisted option value + if (value == invalid_option_value) { + res.errors.emplace(name, SetSessionOptionsResult::Error{ + SetSessionOptionErrorValue::kInvalidValue}); + continue; + } + if (std::holds_alternative(value)) { + session->EraseSessionOption(name); + continue; + } + session->SetSessionOption(name, value); + } + + return res; + } + + arrow::Result GetSessionOptions( + const ServerCallContext& context, + const GetSessionOptionsRequest& request) override { + sql::ServerSessionMiddleware* middleware = + (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + std::shared_ptr session = middleware->GetSession(); + + return GetSessionOptionsResult{session->GetSessionOptions()}; + } + + arrow::Result CloseSession( + const ServerCallContext& context, const CloseSessionRequest& request) override { + sql::ServerSessionMiddleware* middleware = + (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + // FIXME PHOXME try/catch or are we not using exceptions...? + middleware->CloseSession(); + return CloseSessionResult{ CloseSessionStatus::kClosed }; + } +}; + +/// \brief The Session Options scenario. +/// +/// This tests Session Options functionality as well as ServerSessionMiddleware. +class SessionOptionsScenario : public Scenario { + inline const static std::string middleware_key = "sessionmiddleware"; + + Status MakeServer(std::unique_ptr* server, + FlightServerOptions* options) override { + *server = std::make_unique(middleware_key); + + auto id_gen_int = std::make_shared(1000); + options->middleware.emplace_back( + middleware_key, + sql::MakeServerSessionMiddlewareFactory( + [=]() -> std::string { return std::to_string((*id_gen_int)++); })); + + return Status::OK(); + } + + Status MakeClient(FlightClientOptions* options) override { + return Status::OK(); + } + + Status RunClient(std::unique_ptr client) override { +/* ARROW_ASSIGN_OR_RAISE(auto info, + client->GetFlightInfo(FlightDescriptor::Command("expiration"))); + // Renew all endpoints that have expiration time + for (const auto& endpoint : info->endpoints()) { + if (!endpoint.expiration_time.has_value()) { + continue; + } + const auto& expiration_time = endpoint.expiration_time.value(); + auto request = RenewFlightEndpointRequest{endpoint}; + ARROW_ASSIGN_OR_RAISE(auto renewed_endpoint, client->RenewFlightEndpoint(request)); + if (!renewed_endpoint.expiration_time.has_value()) { + return Status::Invalid("Renewed endpoint must have expiration time: ", + renewed_endpoint.ToString()); + } + const auto& renewed_expiration_time = renewed_endpoint.expiration_time.value(); + if (renewed_expiration_time <= expiration_time) { + return Status::Invalid("Renewed endpoint must have newer expiration time\n", + "Original:\n", endpoint.ToString(), "Renewed:\n", + renewed_endpoint.ToString()); + } + } + */ + return Status::OK(); + } +}; + + + + /// \brief The server used for testing PollFlightInfo(). class PollFlightInfoServer : public FlightServerBase { public: diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 958f7132834f8..214e8f94179fd 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -29,9 +29,9 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { std::shared_mutex mutex_; ServerSessionMiddlewareFactory* factory_; const CallHeaders& headers_; - std::shared_ptr session_; + std::shared_ptr session_; std::string session_id_; - const bool existing_session_; + bool existing_session_; public: ServerSessionMiddlewareImpl(ServerSessionMiddlewareFactory* factory, @@ -40,7 +40,7 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { ServerSessionMiddlewareImpl(ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, - std::shared_ptr session, + std::shared_ptr session, std::string session_id) : factory_(factory), headers_(headers), @@ -59,7 +59,7 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { bool HasSession() const override { return static_cast(session_); } - std::shared_ptr GetSession() override { + std::shared_ptr GetSession() override { const std::lock_guard l(mutex_); if (!session_) { auto [id, s] = factory_->CreateNewSession(); @@ -69,6 +69,17 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { return session_; } + void CloseSession() override { + const std::lock_guard l(mutex_); + if (static_cast(session_)) { + // FIXME PHOXME throw or what in C++? + } + factory_->CloseSession(session_id_); + session_id_.clear(); + session_.reset(); + existing_session_ = false; + } + const CallHeaders& GetCallHeaders() const override { return headers_; } }; @@ -149,10 +160,10 @@ Status ServerSessionMiddlewareFactory::StartCall( } /// \brief Get a new, empty session option map & its id key; {"",NULLPTR} on collision. -std::pair> +std::pair> ServerSessionMiddlewareFactory::CreateNewSession() { auto new_id = id_generator_(); - auto session = std::make_shared(); + auto session = std::make_shared(); const std::lock_guard l(session_store_lock_); if (session_store_.count(new_id)) { @@ -164,12 +175,19 @@ ServerSessionMiddlewareFactory::CreateNewSession() { return {new_id, session}; } +void ServerSessionMiddlewareFactory::CloseSession(std::string id) { + const std::lock_guard l(session_store_lock_); + if (!session_store_.erase(id)) { + // FIXME PHOXME throw or what + } +} + std::shared_ptr MakeServerSessionMiddlewareFactory( std::function id_gen) { return std::make_shared(std::move(id_gen)); } -std::optional FlightSqlSession::GetSessionOption( +std::optional FlightSession::GetSessionOption( const std::string& name) { const std::shared_lock l(map_lock_); auto it = map_.find(name); @@ -180,13 +198,18 @@ std::optional FlightSqlSession::GetSessionOption( } } -void FlightSqlSession::SetSessionOption(const std::string& name, +std::map FlightSession::GetSessionOptions() { + const std::shared_lock l(map_lock_); + return map_; +} + +void FlightSession::SetSessionOption(const std::string& name, const SessionOptionValue value) { const std::lock_guard l(map_lock_); map_[name] = std::move(value); } -void FlightSqlSession::EraseSessionOption(const std::string& name) { +void FlightSession::EraseSessionOption(const std::string& name) { const std::lock_guard l(map_lock_); map_.erase(name); } diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index e9dbb6a19d92b..f59f95cc9d749 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -35,7 +35,7 @@ namespace sql { static constexpr char const kSessionCookieName[] = "arrow_flight_session_id"; -class ARROW_FLIGHT_SQL_EXPORT FlightSqlSession { +class ARROW_FLIGHT_SQL_EXPORT FlightSession { protected: std::map map_; std::shared_mutex map_lock_; @@ -43,6 +43,10 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSqlSession { public: /// \brief Get session option by name std::optional GetSessionOption(const std::string& name); + /// \brief Get a copy of the session options map. + /// + /// The returned options map may be modified by further calls to this FlightSession + std::map GetSessionOptions(); /// \brief Set session option by name to given value void SetSessionOption(const std::string& name, const SessionOptionValue value); /// \brief Idempotently remove name from this session @@ -62,7 +66,9 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware /// \brief Get existing or new call-associated session /// /// May return NULLPTR if there is an id generation collision. - virtual std::shared_ptr GetSession() = 0; + virtual std::shared_ptr GetSession() = 0; + /// Close the current session. + virtual void CloseSession() = 0; /// \brief Get request headers, in lieu of a provided or created session. virtual const CallHeaders& GetCallHeaders() const = 0; }; diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h index 56becf56e0c1f..b428aca66e8ac 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h @@ -36,7 +36,7 @@ namespace sql { class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddlewareFactory : public ServerMiddlewareFactory { protected: - std::map> session_store_; + std::map> session_store_; std::shared_mutex session_store_lock_; std::function id_generator_; @@ -50,7 +50,10 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddlewareFactory std::shared_ptr* middleware) override; /// \brief Get a new, empty session option map and its id key. - std::pair> CreateNewSession(); + std::pair> CreateNewSession(); + /// \brief Close the session identified by 'id'. + /// \param id The string id of the session to close. + void CloseSession(std::string id); }; } // namespace sql diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java index b4b34f584627d..f29028547c452 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsProducer.java @@ -56,13 +56,13 @@ public void setSessionOptions(SetSessionOptionsRequest request, CallContext cont ServerSessionMiddleware middleware = context.getMiddleware(sessionMiddlewareKey); ServerSessionMiddleware.Session session = middleware.getSession(); for (Map.Entry entry : request.getSessionOptions().entrySet()) { - // Blacklisted value name + // Blacklisted option name if (entry.getKey().equals("lol_invalid")) { errors.put(entry.getKey(), new SetSessionOptionsResult.Error(SetSessionOptionsResult.ErrorValue.INVALID_NAME)); continue; } - // Blacklisted value + // Blacklisted option value // Recommend using a visitor to check polymorphic equality, but this check is easy if (entry.getValue().equals(invalidOptionValue)) { errors.put(entry.getKey(), From 4134aa0809d76490b16781736ae803e5eda49b7d Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 21 Jan 2024 19:08:47 -0800 Subject: [PATCH 169/195] [C++ builds] checkpoint --- .../integration_tests/test_integration.cc | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index d97178701fabc..c4f138bfc143b 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -28,6 +28,7 @@ #include "arrow/array/array_nested.h" #include "arrow/array/array_primitive.h" #include "arrow/array/builder_primitive.h" +#include "arrow/flight/client_cookie_middleware.h" #include "arrow/flight/client_middleware.h" #include "arrow/flight/server_middleware.h" #include "arrow/flight/sql/client.h" @@ -826,15 +827,15 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { /// /// This tests Session Options functionality as well as ServerSessionMiddleware. class SessionOptionsScenario : public Scenario { - inline const static std::string middleware_key = "sessionmiddleware"; + inline const static std::string server_middleware_key = "sessionmiddleware"; Status MakeServer(std::unique_ptr* server, FlightServerOptions* options) override { - *server = std::make_unique(middleware_key); + *server = std::make_unique(server_middleware_key); auto id_gen_int = std::make_shared(1000); options->middleware.emplace_back( - middleware_key, + server_middleware_key, sql::MakeServerSessionMiddlewareFactory( [=]() -> std::string { return std::to_string((*id_gen_int)++); })); @@ -842,10 +843,25 @@ class SessionOptionsScenario : public Scenario { } Status MakeClient(FlightClientOptions* options) override { + options->middleware.emplace_back(GetCookieFactory()); return Status::OK(); } - Status RunClient(std::unique_ptr client) override { + Status RunClient(std::unique_ptr flight_client) override { + sql::FlightSqlClient client{std::move(flight_client)}; + + auto req1 = SetSessionOptionsRequest{{ + {"foolong", 123L}, + {"bardouble", 456.0}, + {"lol_invalid", "this won't get set"}, + {"key_with_invalid_value", "lol_invalid"}, + {"big_ol_string_list", std::vector{ + "a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"}} + }}; + ARROW_ASSIGN_OR_RAISE(auto res1, client.SetSessionOptions({}, req1)); + // FIXME PHOXME + + /* ARROW_ASSIGN_OR_RAISE(auto info, client->GetFlightInfo(FlightDescriptor::Command("expiration"))); // Renew all endpoints that have expiration time @@ -2083,6 +2099,9 @@ Status GetScenario(const std::string& scenario_name, std::shared_ptr* } else if (scenario_name == "expiration_time:renew_flight_endpoint") { *out = std::make_shared(); return Status::OK(); + } else if (scenario_name == "session_options") { + *out = std::make_shared(); + return Status::OK(); } else if (scenario_name == "poll_flight_info") { *out = std::make_shared(); return Status::OK(); From b5bf2abd3c240c402c62abeb0b948736afa25a88 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 21 Jan 2024 19:14:28 -0800 Subject: [PATCH 170/195] [C++ builds] checkpoint --- .../arrow/flight/integration_tests/flight_integration_test.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc b/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc index 67c7ee85f59d3..202fd3db434e4 100644 --- a/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc +++ b/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc @@ -71,6 +71,10 @@ TEST(FlightIntegration, ExpirationTimeRenewFlightEndpoint) { ASSERT_OK(RunScenario("expiration_time:renew_flight_endpoint")); } +TEST(FlightIntegration, SessionOptions) { + ASSERT_OK(RunScenario("session_options")); +} + TEST(FlightIntegration, PollFlightInfo) { ASSERT_OK(RunScenario("poll_flight_info")); } TEST(FlightIntegration, AppMetadataFlightInfoEndpoint) { From 26ffb8ab8d3a0f8abb5458ffa99b427514d521c6 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 21 Jan 2024 20:00:43 -0800 Subject: [PATCH 171/195] [C++ builds] checkpoint --- .../integration_tests/test_integration.cc | 52 +++++++++++-------- .../tests/SessionOptionsScenario.java | 2 +- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index c4f138bfc143b..f1e2ca73efb56 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -850,6 +850,7 @@ class SessionOptionsScenario : public Scenario { Status RunClient(std::unique_ptr flight_client) override { sql::FlightSqlClient client{std::move(flight_client)}; + // Set auto req1 = SetSessionOptionsRequest{{ {"foolong", 123L}, {"bardouble", 456.0}, @@ -859,31 +860,36 @@ class SessionOptionsScenario : public Scenario { "a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"}} }}; ARROW_ASSIGN_OR_RAISE(auto res1, client.SetSessionOptions({}, req1)); + // Some errors + if (!(res1.errors == std::map{ + {"lol_invalid", SetSessionOptionsResult::Error{ + SetSessionOptionErrorValue::kInvalidName}}, + {"key_with_invalid_value", SetSessionOptionsResult::Error{ + SetSessionOptionErrorValue::kInvalidValue}}})) { + return Status::Invalid("res1 incorrect"); + } + // Some set, some omitted due to above errors + ARROW_ASSIGN_OR_RAISE(auto res2, client.GetSessionOptions({}, {})); + if (!(res2.session_options == std::map{ + {"foolong", 123L}, + {"bardouble", 456.0}, + {"big_ol_string_list", std::vector{ + "a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"}}})) { + return Status::Invalid("res2 incorrect"); + } + // Update + ARROW_ASSIGN_OR_RAISE(auto res3, client.SetSessionOptions({}, SetSessionOptionsRequest{{ + {"foolong", std::monostate{}}, + {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"} + }})); + ARROW_ASSIGN_OR_RAISE(auto res4, client.GetSessionOptions({}, {})); + if (!(res4.session_options == std::map{ + {"bardouble", 456.0}, + {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}})) { + return Status::Invalid("res4 not ok"); + } // FIXME PHOXME - -/* ARROW_ASSIGN_OR_RAISE(auto info, - client->GetFlightInfo(FlightDescriptor::Command("expiration"))); - // Renew all endpoints that have expiration time - for (const auto& endpoint : info->endpoints()) { - if (!endpoint.expiration_time.has_value()) { - continue; - } - const auto& expiration_time = endpoint.expiration_time.value(); - auto request = RenewFlightEndpointRequest{endpoint}; - ARROW_ASSIGN_OR_RAISE(auto renewed_endpoint, client->RenewFlightEndpoint(request)); - if (!renewed_endpoint.expiration_time.has_value()) { - return Status::Invalid("Renewed endpoint must have expiration time: ", - renewed_endpoint.ToString()); - } - const auto& renewed_expiration_time = renewed_endpoint.expiration_time.value(); - if (renewed_expiration_time <= expiration_time) { - return Status::Invalid("Renewed endpoint must have newer expiration time\n", - "Original:\n", endpoint.ToString(), "Renewed:\n", - renewed_endpoint.ToString()); - } - } - */ return Status::OK(); } }; diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index 2618e217a28c6..8a390e3ae689b 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -86,7 +86,7 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig SetSessionOptionsResult.ErrorValue.INVALID_VALUE)) .build(), res1.getErrors()); - // Some set, some omitted due to errors + // Some set, some omitted due to above errors GetSessionOptionsResult res2 = client.getSessionOptions(new GetSessionOptionsRequest()); IntegrationAssertions.assertEquals(ImmutableMap.builder() .put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)) From 0f8fae3ab50ed8e62af3e905c951cd6dce7a63bf Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 21 Jan 2024 21:34:13 -0800 Subject: [PATCH 172/195] [C++ builds] BUG CHECKPOINT --- cpp/src/arrow/flight/cookie_internal.cc | 3 ++ .../integration_tests/test_integration.cc | 31 +++++++++++-------- .../flight/sql/server_session_middleware.cc | 10 +++++- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/cpp/src/arrow/flight/cookie_internal.cc b/cpp/src/arrow/flight/cookie_internal.cc index 921f017313611..aa3d394712700 100644 --- a/cpp/src/arrow/flight/cookie_internal.cc +++ b/cpp/src/arrow/flight/cookie_internal.cc @@ -35,6 +35,7 @@ #include #include #include +#include // FIXME PHOXME #include #include #include @@ -250,10 +251,12 @@ void CookieCache::DiscardExpiredCookies() { } void CookieCache::UpdateCachedCookies(const CallHeaders& incoming_headers) { + std::cerr << "Looking for set-cookie header..." << std::endl; CookieHeaderPair header_values = incoming_headers.equal_range("set-cookie"); const std::lock_guard guard(mutex_); for (auto it = header_values.first; it != header_values.second; ++it) { + std::cerr << "Examining 'set-cookie' header..." << std::endl; const std::string_view& value = it->second; Cookie cookie = Cookie::Parse(value); diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index f1e2ca73efb56..fbfe78f796392 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -746,11 +746,6 @@ class ExpirationTimeRenewFlightEndpointScenario : public Scenario { } }; - - - -// FIXME PHOXME whitespace and after class - /// \brief The server used for testing Session Options. /// /// setSessionOptions has a blacklisted option name and string option value, @@ -797,7 +792,9 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { session->EraseSessionOption(name); continue; } + std::cerr << "Setting option " << name << std::endl; session->SetSessionOption(name, value); + std::cerr << "Session now contains " << session->GetSessionOptions().size() << std::endl; } return res; @@ -808,9 +805,14 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { const GetSessionOptionsRequest& request) override { sql::ServerSessionMiddleware* middleware = (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + if (!middleware->HasSession()) { + // FIXME PHOXME post NOT_FOUND somehow?! + } std::shared_ptr session = middleware->GetSession(); - return GetSessionOptionsResult{session->GetSessionOptions()}; + GetSessionOptionsResult res{session->GetSessionOptions()}; + std::cerr << "Server returning GetSessionOptionsResult: " << res.ToString() << std::endl; + return res; } arrow::Result CloseSession( @@ -866,7 +868,7 @@ class SessionOptionsScenario : public Scenario { SetSessionOptionErrorValue::kInvalidName}}, {"key_with_invalid_value", SetSessionOptionsResult::Error{ SetSessionOptionErrorValue::kInvalidValue}}})) { - return Status::Invalid("res1 incorrect"); + return Status::Invalid("res1 incorrect: " + res1.ToString()); } // Some set, some omitted due to above errors ARROW_ASSIGN_OR_RAISE(auto res2, client.GetSessionOptions({}, {})); @@ -875,7 +877,7 @@ class SessionOptionsScenario : public Scenario { {"bardouble", 456.0}, {"big_ol_string_list", std::vector{ "a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"}}})) { - return Status::Invalid("res2 incorrect"); + return Status::Invalid("res2 incorrect: " + res2.ToString()); } // Update ARROW_ASSIGN_OR_RAISE(auto res3, client.SetSessionOptions({}, SetSessionOptionsRequest{{ @@ -886,17 +888,20 @@ class SessionOptionsScenario : public Scenario { if (!(res4.session_options == std::map{ {"bardouble", 456.0}, {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}})) { - return Status::Invalid("res4 not ok"); + return Status::Invalid("res4 incorrect: " + res4.ToString()); + } + // Close and reinitialize + ARROW_RETURN_NOT_OK(client.CloseSession({}, {})); + ARROW_RETURN_NOT_OK(client.SetSessionOptions({}, {})); + ARROW_ASSIGN_OR_RAISE(auto res7, client.GetSessionOptions({}, {})); + if (!(res7.session_options == std::map{})) { + return Status::Invalid("res7 incorrect: " + res7.ToString()); } - // FIXME PHOXME return Status::OK(); } }; - - - /// \brief The server used for testing PollFlightInfo(). class PollFlightInfoServer : public FlightServerBase { public: diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 214e8f94179fd..5fe2f463e3751 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -15,6 +15,7 @@ // specific language governing permissions and limitations // under the License. +#include #include #include "arrow/flight/sql/server_session_middleware.h" @@ -50,9 +51,10 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { void SendingHeaders(AddCallHeaders* add_call_headers) override { if (!existing_session_ && session_) { + std::cerr << "ServerSessionMiddlewareImpl@" << this << " Adding set-cookie header..." << std::endl; add_call_headers->AddHeader( "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); - } + } else std::cerr << "ServerSessionMiddlewareImpl@" << this << " Did not add set-cookie header, existing_session is: " << existing_session_ << ", session_ is: " << session_ << std::endl; } void CallCompleted(const Status&) override {} @@ -63,9 +65,11 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { const std::lock_guard l(mutex_); if (!session_) { auto [id, s] = factory_->CreateNewSession(); + std::cerr << "ServerSessionMiddlewareImpl@" << this << " Created new session with id " << id << ", address " << s << std::endl; session_ = std::move(s); session_id_ = std::move(id); } + std::cerr << "ServerSessionMiddlewareImpl@" << this << " Returning session at " << session_ << std::endl; return session_; } @@ -124,11 +128,13 @@ ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { Status ServerSessionMiddlewareFactory::StartCall( const CallInfo&, const CallHeaders& incoming_headers, std::shared_ptr* middleware) { + std::cerr << "ServerSessionMiddlewareFactory::StartCall: session_store_.size() is " << session_store_.size() << std::endl; std::string session_id; const std::pair& headers_it_pr = incoming_headers.equal_range("cookie"); for (auto itr = headers_it_pr.first; itr != headers_it_pr.second; ++itr) { + std::cerr << "Examining 'cookie' header..." << std::endl; const std::string_view& cookie_header = itr->second; const std::vector> cookies = ParseCookieString(cookie_header); @@ -200,6 +206,7 @@ std::optional FlightSession::GetSessionOption( std::map FlightSession::GetSessionOptions() { const std::shared_lock l(map_lock_); + std::cerr << "FlightSession returning SessionOptions map of size " << map_.size() << std::endl; return map_; } @@ -207,6 +214,7 @@ void FlightSession::SetSessionOption(const std::string& name, const SessionOptionValue value) { const std::lock_guard l(map_lock_); map_[name] = std::move(value); + std::cerr << "FlightSession now contains " << map_.size() << " entries" << std::endl; } void FlightSession::EraseSessionOption(const std::string& name) { From 028f0a5731bc83f3be7ff74b384484dcb31e84c4 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 22 Jan 2024 13:46:35 -0800 Subject: [PATCH 173/195] [C++ builds] Add session cookie expiry --- cpp/src/arrow/flight/sql/server_session_middleware.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 5fe2f463e3751..a8511f10741d0 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -32,6 +32,7 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { const CallHeaders& headers_; std::shared_ptr session_; std::string session_id_; + std::string closed_session_id_; bool existing_session_; public: @@ -55,6 +56,10 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { add_call_headers->AddHeader( "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); } else std::cerr << "ServerSessionMiddlewareImpl@" << this << " Did not add set-cookie header, existing_session is: " << existing_session_ << ", session_ is: " << session_ << std::endl; + if (!closed_session_id_.empty()) { + add_call_headers->AddHeader( + "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_ + "; Max-Age=0"); + } } void CallCompleted(const Status&) override {} @@ -79,6 +84,7 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { // FIXME PHOXME throw or what in C++? } factory_->CloseSession(session_id_); + closed_session_id_ = std::move(session_id_); session_id_.clear(); session_.reset(); existing_session_ = false; From 95d0499aca461ca303194ea9fa43e1e0936a0133 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 23 Jan 2024 14:06:07 -0800 Subject: [PATCH 174/195] [Java builds] Fix NoOpSessionOptionValueVisitor iface --- .../flight/NoOpSessionOptionValueVisitor.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/NoOpSessionOptionValueVisitor.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/NoOpSessionOptionValueVisitor.java index bf2abdda13428..c951cce0ed42d 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/NoOpSessionOptionValueVisitor.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/NoOpSessionOptionValueVisitor.java @@ -21,40 +21,42 @@ * A helper to facilitate easier anonymous subclass declaration. * * Implementations need only override callbacks for types they wish to do something with. + * + * @param Return type of the visit operation. */ -public class NoOpSessionOptionValueVisitor implements SessionOptionValueVisitor { +public class NoOpSessionOptionValueVisitor implements SessionOptionValueVisitor { /** * A callback to handle SessionOptionValue containing a String. */ - public Object visit(String value) { + public T visit(String value) { return null; } /** * A callback to handle SessionOptionValue containing a boolean. */ - public Object visit(boolean value) { + public T visit(boolean value) { return null; } /** * A callback to handle SessionOptionValue containing a long. */ - public Object visit(long value) { + public T visit(long value) { return null; } /** * A callback to handle SessionOptionValue containing a double. */ - public Object visit(double value) { + public T visit(double value) { return null; } /** * A callback to handle SessionOptionValue containing an array of String. */ - public Object visit(String[] value) { + public T visit(String[] value) { return null; } @@ -64,7 +66,7 @@ public Object visit(String[] value) { * By convention, an attempt to set a valueless SessionOptionValue should * attempt to unset or clear the named option value on the server. */ - public Object visit(Void value) { + public T visit(Void value) { return null; } } From e83c8bb0d26865405e62fd4c4b820594eb7332ea Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 23 Jan 2024 16:39:46 -0800 Subject: [PATCH 175/195] [C++ builds & passes] Bodge around middleware gap --- .../flight/integration_tests/test_integration.cc | 14 ++------------ .../arrow/flight/sql/server_session_middleware.cc | 11 ++++++++--- .../arrow/flight/sql/server_session_middleware.h | 2 ++ 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index fbfe78f796392..7741d6ecfbe77 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -817,11 +817,8 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { arrow::Result CloseSession( const ServerCallContext& context, const CloseSessionRequest& request) override { - sql::ServerSessionMiddleware* middleware = - (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); - // FIXME PHOXME try/catch or are we not using exceptions...? - middleware->CloseSession(); - return CloseSessionResult{ CloseSessionStatus::kClosed }; + // Unsupported until C++ middleware SendingHeaders handling fixed. + return CloseSessionResult{ CloseSessionStatus::kNotClosable }; } }; @@ -890,13 +887,6 @@ class SessionOptionsScenario : public Scenario { {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}})) { return Status::Invalid("res4 incorrect: " + res4.ToString()); } - // Close and reinitialize - ARROW_RETURN_NOT_OK(client.CloseSession({}, {})); - ARROW_RETURN_NOT_OK(client.SetSessionOptions({}, {})); - ARROW_ASSIGN_OR_RAISE(auto res7, client.GetSessionOptions({}, {})); - if (!(res7.session_options == std::map{})) { - return Status::Invalid("res7 incorrect: " + res7.ToString()); - } return Status::OK(); } diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index a8511f10741d0..43bce2d6afa60 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -43,12 +43,13 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { ServerSessionMiddlewareImpl(ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, std::shared_ptr session, - std::string session_id) + std::string session_id, + bool existing_session = true) : factory_(factory), headers_(headers), session_(std::move(session)), session_id_(std::move(session_id)), - existing_session_(true) {} + existing_session_(existing_session) {} void SendingHeaders(AddCallHeaders* add_call_headers) override { if (!existing_session_ && session_) { @@ -156,7 +157,11 @@ Status ServerSessionMiddlewareFactory::StartCall( if (session_id.empty()) { // No cookie was found - *middleware = std::make_shared(this, incoming_headers); + // Temporary workaround until middleware handling fixed + auto [id, s] = CreateNewSession(); + std::cerr << "Created new session as fallback behaviour for broken middleware handling" << std::endl; + *middleware = std::make_shared(this, incoming_headers, + std::move(s), id, false); } else { const std::shared_lock l(session_store_lock_); if (auto it = session_store_.find(session_id); it == session_store_.end()) { diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index f59f95cc9d749..bb4128a39de6c 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -68,6 +68,8 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware /// May return NULLPTR if there is an id generation collision. virtual std::shared_ptr GetSession() = 0; /// Close the current session. + /// + /// This is presently unsupported in C++ until middleware handling can be fixed. virtual void CloseSession() = 0; /// \brief Get request headers, in lieu of a provided or created session. virtual const CallHeaders& GetCallHeaders() const = 0; From 3904ce72cdfd808a199408096fe6f3fb32f08f3f Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 24 Jan 2024 12:12:22 -0800 Subject: [PATCH 176/195] [C++ builds] remove debug spew --- cpp/src/arrow/flight/cookie_internal.cc | 3 --- .../flight/integration_tests/test_integration.cc | 6 +----- cpp/src/arrow/flight/sql/server_session_middleware.cc | 11 +---------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/cpp/src/arrow/flight/cookie_internal.cc b/cpp/src/arrow/flight/cookie_internal.cc index aa3d394712700..921f017313611 100644 --- a/cpp/src/arrow/flight/cookie_internal.cc +++ b/cpp/src/arrow/flight/cookie_internal.cc @@ -35,7 +35,6 @@ #include #include #include -#include // FIXME PHOXME #include #include #include @@ -251,12 +250,10 @@ void CookieCache::DiscardExpiredCookies() { } void CookieCache::UpdateCachedCookies(const CallHeaders& incoming_headers) { - std::cerr << "Looking for set-cookie header..." << std::endl; CookieHeaderPair header_values = incoming_headers.equal_range("set-cookie"); const std::lock_guard guard(mutex_); for (auto it = header_values.first; it != header_values.second; ++it) { - std::cerr << "Examining 'set-cookie' header..." << std::endl; const std::string_view& value = it->second; Cookie cookie = Cookie::Parse(value); diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index 7741d6ecfbe77..c14ce76d6b5ba 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -792,9 +792,7 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { session->EraseSessionOption(name); continue; } - std::cerr << "Setting option " << name << std::endl; session->SetSessionOption(name, value); - std::cerr << "Session now contains " << session->GetSessionOptions().size() << std::endl; } return res; @@ -810,9 +808,7 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { } std::shared_ptr session = middleware->GetSession(); - GetSessionOptionsResult res{session->GetSessionOptions()}; - std::cerr << "Server returning GetSessionOptionsResult: " << res.ToString() << std::endl; - return res; + return GetSessionOptionsResult{session->GetSessionOptions()}; } arrow::Result CloseSession( diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 43bce2d6afa60..a42c0f1d2dacd 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -15,7 +15,6 @@ // specific language governing permissions and limitations // under the License. -#include #include #include "arrow/flight/sql/server_session_middleware.h" @@ -53,10 +52,9 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { void SendingHeaders(AddCallHeaders* add_call_headers) override { if (!existing_session_ && session_) { - std::cerr << "ServerSessionMiddlewareImpl@" << this << " Adding set-cookie header..." << std::endl; add_call_headers->AddHeader( "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_); - } else std::cerr << "ServerSessionMiddlewareImpl@" << this << " Did not add set-cookie header, existing_session is: " << existing_session_ << ", session_ is: " << session_ << std::endl; + } if (!closed_session_id_.empty()) { add_call_headers->AddHeader( "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_ + "; Max-Age=0"); @@ -71,11 +69,9 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { const std::lock_guard l(mutex_); if (!session_) { auto [id, s] = factory_->CreateNewSession(); - std::cerr << "ServerSessionMiddlewareImpl@" << this << " Created new session with id " << id << ", address " << s << std::endl; session_ = std::move(s); session_id_ = std::move(id); } - std::cerr << "ServerSessionMiddlewareImpl@" << this << " Returning session at " << session_ << std::endl; return session_; } @@ -135,13 +131,11 @@ ServerSessionMiddlewareFactory::ParseCookieString(const std::string_view& s) { Status ServerSessionMiddlewareFactory::StartCall( const CallInfo&, const CallHeaders& incoming_headers, std::shared_ptr* middleware) { - std::cerr << "ServerSessionMiddlewareFactory::StartCall: session_store_.size() is " << session_store_.size() << std::endl; std::string session_id; const std::pair& headers_it_pr = incoming_headers.equal_range("cookie"); for (auto itr = headers_it_pr.first; itr != headers_it_pr.second; ++itr) { - std::cerr << "Examining 'cookie' header..." << std::endl; const std::string_view& cookie_header = itr->second; const std::vector> cookies = ParseCookieString(cookie_header); @@ -159,7 +153,6 @@ Status ServerSessionMiddlewareFactory::StartCall( // No cookie was found // Temporary workaround until middleware handling fixed auto [id, s] = CreateNewSession(); - std::cerr << "Created new session as fallback behaviour for broken middleware handling" << std::endl; *middleware = std::make_shared(this, incoming_headers, std::move(s), id, false); } else { @@ -217,7 +210,6 @@ std::optional FlightSession::GetSessionOption( std::map FlightSession::GetSessionOptions() { const std::shared_lock l(map_lock_); - std::cerr << "FlightSession returning SessionOptions map of size " << map_.size() << std::endl; return map_; } @@ -225,7 +217,6 @@ void FlightSession::SetSessionOption(const std::string& name, const SessionOptionValue value) { const std::lock_guard l(map_lock_); map_[name] = std::move(value); - std::cerr << "FlightSession now contains " << map_.size() << " entries" << std::endl; } void FlightSession::EraseSessionOption(const std::string& name) { From 1b6840fcecd430b17801cf8a617e9df59132149f Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 24 Jan 2024 12:45:08 -0800 Subject: [PATCH 177/195] [C++ builds & passes] Update middleware & tests --- .../integration_tests/test_integration.cc | 14 ++++++++------ .../flight/sql/server_session_middleware.cc | 18 ++++++++++++------ .../flight/sql/server_session_middleware.h | 5 +++-- .../sql/server_session_middleware_factory.h | 2 +- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index c14ce76d6b5ba..7f2d8f62bb130 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -759,7 +759,6 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { std::map session_store_; public: - // FIXME PHOXME need to handle middleware lookup token wherever SessionOptionsServer(std::string session_middleware_key) : FlightSqlServerBase(), session_middleware_key(std::move(session_middleware_key)) { @@ -773,7 +772,7 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { sql::ServerSessionMiddleware* middleware = (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); - std::shared_ptr session = middleware->GetSession(); + ARROW_ASSIGN_OR_RAISE(std::shared_ptr session, middleware->GetSession()); for (const auto& [name, value] : request.session_options) { // Blacklisted value name @@ -804,17 +803,20 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { sql::ServerSessionMiddleware* middleware = (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); if (!middleware->HasSession()) { - // FIXME PHOXME post NOT_FOUND somehow?! + return Status::Invalid("No existing session to get options from."); } - std::shared_ptr session = middleware->GetSession(); + ARROW_ASSIGN_OR_RAISE(std::shared_ptr session, middleware->GetSession()); return GetSessionOptionsResult{session->GetSessionOptions()}; } arrow::Result CloseSession( const ServerCallContext& context, const CloseSessionRequest& request) override { - // Unsupported until C++ middleware SendingHeaders handling fixed. - return CloseSessionResult{ CloseSessionStatus::kNotClosable }; + // Broken (does not expire cookie) until C++ middleware SendingHeaders handling fixed. + sql::ServerSessionMiddleware* middleware = + (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + ARROW_RETURN_NOT_OK(middleware->CloseSession()); + return CloseSessionResult{ CloseSessionStatus::kClosed }; } }; diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index a42c0f1d2dacd..27c4b140ed89c 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -65,26 +65,31 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { bool HasSession() const override { return static_cast(session_); } - std::shared_ptr GetSession() override { + arrow::Result> GetSession() override { const std::lock_guard l(mutex_); if (!session_) { auto [id, s] = factory_->CreateNewSession(); session_ = std::move(s); session_id_ = std::move(id); } + if (!static_cast(session_)) { + return Status::UnknownError("Error creating session."); + } return session_; } - void CloseSession() override { + Status CloseSession() override { const std::lock_guard l(mutex_); if (static_cast(session_)) { - // FIXME PHOXME throw or what in C++? + return Status::Invalid("Nonexistent session cannot be closed."); } - factory_->CloseSession(session_id_); + ARROW_RETURN_NOT_OK(factory_->CloseSession(session_id_)); closed_session_id_ = std::move(session_id_); session_id_.clear(); session_.reset(); existing_session_ = false; + + return Status::OK(); } const CallHeaders& GetCallHeaders() const override { return headers_; } @@ -185,11 +190,12 @@ ServerSessionMiddlewareFactory::CreateNewSession() { return {new_id, session}; } -void ServerSessionMiddlewareFactory::CloseSession(std::string id) { +Status ServerSessionMiddlewareFactory::CloseSession(std::string id) { const std::lock_guard l(session_store_lock_); if (!session_store_.erase(id)) { - // FIXME PHOXME throw or what + return Status::KeyError("Invalid or nonexistent session cannot be closed."); } + return Status::OK(); } std::shared_ptr MakeServerSessionMiddlewareFactory( diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index bb4128a39de6c..66a5bc28d65d8 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -28,6 +28,7 @@ #include "arrow/flight/server_middleware.h" #include "arrow/flight/sql/types.h" +#include "arrow/status.h" namespace arrow { namespace flight { @@ -66,11 +67,11 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware /// \brief Get existing or new call-associated session /// /// May return NULLPTR if there is an id generation collision. - virtual std::shared_ptr GetSession() = 0; + virtual arrow::Result> GetSession() = 0; /// Close the current session. /// /// This is presently unsupported in C++ until middleware handling can be fixed. - virtual void CloseSession() = 0; + virtual Status CloseSession() = 0; /// \brief Get request headers, in lieu of a provided or created session. virtual const CallHeaders& GetCallHeaders() const = 0; }; diff --git a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h index b428aca66e8ac..2613c572eefc2 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware_factory.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware_factory.h @@ -53,7 +53,7 @@ class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddlewareFactory std::pair> CreateNewSession(); /// \brief Close the session identified by 'id'. /// \param id The string id of the session to close. - void CloseSession(std::string id); + Status CloseSession(std::string id); }; } // namespace sql From 61a2a3f33a4509ef495b78a27204eb7ab77f4492 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 24 Jan 2024 14:11:06 -0800 Subject: [PATCH 178/195] [C++ builds & passes] CI linter fixups --- .../flight_integration_test.cc | 4 +- .../integration_tests/test_integration.cc | 84 ++++++++++--------- .../flight/sql/server_session_middleware.cc | 8 +- 3 files changed, 50 insertions(+), 46 deletions(-) diff --git a/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc b/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc index 202fd3db434e4..6f3115cc5ab8a 100644 --- a/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc +++ b/cpp/src/arrow/flight/integration_tests/flight_integration_test.cc @@ -71,9 +71,7 @@ TEST(FlightIntegration, ExpirationTimeRenewFlightEndpoint) { ASSERT_OK(RunScenario("expiration_time:renew_flight_endpoint")); } -TEST(FlightIntegration, SessionOptions) { - ASSERT_OK(RunScenario("session_options")); -} +TEST(FlightIntegration, SessionOptions) { ASSERT_OK(RunScenario("session_options")); } TEST(FlightIntegration, PollFlightInfo) { ASSERT_OK(RunScenario("poll_flight_info")); } diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index 7f2d8f62bb130..d156bad200279 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -718,7 +718,7 @@ class ExpirationTimeRenewFlightEndpointScenario : public Scenario { return Status::OK(); } - Status MakeClient(FlightClientOptions* options) override {return Status::OK(); } + Status MakeClient(FlightClientOptions* options) override { return Status::OK(); } Status RunClient(std::unique_ptr client) override { ARROW_ASSIGN_OR_RAISE(auto info, @@ -751,19 +751,17 @@ class ExpirationTimeRenewFlightEndpointScenario : public Scenario { /// setSessionOptions has a blacklisted option name and string option value, /// both "lol_invalid", which will result in errors attempting to set either. class SessionOptionsServer : public sql::FlightSqlServerBase { - inline const static std::string invalid_option_name = "lol_invalid"; - inline const static SessionOptionValue invalid_option_value = "lol_invalid"; + static inline const std::string invalid_option_name = "lol_invalid"; + static inline const SessionOptionValue invalid_option_value = "lol_invalid"; const std::string session_middleware_key; // These will never be threaded so using a plain map and no lock std::map session_store_; public: - SessionOptionsServer(std::string session_middleware_key) + explicit SessionOptionsServer(std::string session_middleware_key) : FlightSqlServerBase(), - session_middleware_key(std::move(session_middleware_key)) { - - } + session_middleware_key(std::move(session_middleware_key)) {} arrow::Result SetSessionOptions( const ServerCallContext& context, @@ -771,8 +769,9 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { SetSessionOptionsResult res; sql::ServerSessionMiddleware* middleware = - (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); - ARROW_ASSIGN_OR_RAISE(std::shared_ptr session, middleware->GetSession()); + (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + ARROW_ASSIGN_OR_RAISE(std::shared_ptr session, + middleware->GetSession()); for (const auto& [name, value] : request.session_options) { // Blacklisted value name @@ -801,11 +800,12 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { const ServerCallContext& context, const GetSessionOptionsRequest& request) override { sql::ServerSessionMiddleware* middleware = - (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); if (!middleware->HasSession()) { return Status::Invalid("No existing session to get options from."); } - ARROW_ASSIGN_OR_RAISE(std::shared_ptr session, middleware->GetSession()); + ARROW_ASSIGN_OR_RAISE(std::shared_ptr session, + middleware->GetSession()); return GetSessionOptionsResult{session->GetSessionOptions()}; } @@ -814,9 +814,9 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { const ServerCallContext& context, const CloseSessionRequest& request) override { // Broken (does not expire cookie) until C++ middleware SendingHeaders handling fixed. sql::ServerSessionMiddleware* middleware = - (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); ARROW_RETURN_NOT_OK(middleware->CloseSession()); - return CloseSessionResult{ CloseSessionStatus::kClosed }; + return CloseSessionResult{CloseSessionStatus::kClosed}; } }; @@ -824,7 +824,7 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { /// /// This tests Session Options functionality as well as ServerSessionMiddleware. class SessionOptionsScenario : public Scenario { - inline const static std::string server_middleware_key = "sessionmiddleware"; + static inline const std::string server_middleware_key = "sessionmiddleware"; Status MakeServer(std::unique_ptr* server, FlightServerOptions* options) override { @@ -848,41 +848,47 @@ class SessionOptionsScenario : public Scenario { sql::FlightSqlClient client{std::move(flight_client)}; // Set - auto req1 = SetSessionOptionsRequest{{ - {"foolong", 123L}, - {"bardouble", 456.0}, - {"lol_invalid", "this won't get set"}, - {"key_with_invalid_value", "lol_invalid"}, - {"big_ol_string_list", std::vector{ - "a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"}} - }}; + auto req1 = SetSessionOptionsRequest{ + {{"foolong", 123L}, + {"bardouble", 456.0}, + {"lol_invalid", "this won't get set"}, + {"key_with_invalid_value", "lol_invalid"}, + {"big_ol_string_list", std::vector{"a", "b", "sea", "dee", " ", + " ", "geee", "(づ。◕‿‿◕。)づ"}}}}; ARROW_ASSIGN_OR_RAISE(auto res1, client.SetSessionOptions({}, req1)); // Some errors - if (!(res1.errors == std::map{ - {"lol_invalid", SetSessionOptionsResult::Error{ - SetSessionOptionErrorValue::kInvalidName}}, - {"key_with_invalid_value", SetSessionOptionsResult::Error{ - SetSessionOptionErrorValue::kInvalidValue}}})) { + if (!(res1.errors == + std::map{ + {"lol_invalid", + SetSessionOptionsResult::Error{SetSessionOptionErrorValue::kInvalidName}}, + {"key_with_invalid_value", + SetSessionOptionsResult::Error{ + SetSessionOptionErrorValue::kInvalidValue}}})) { return Status::Invalid("res1 incorrect: " + res1.ToString()); } // Some set, some omitted due to above errors ARROW_ASSIGN_OR_RAISE(auto res2, client.GetSessionOptions({}, {})); - if (!(res2.session_options == std::map{ - {"foolong", 123L}, - {"bardouble", 456.0}, - {"big_ol_string_list", std::vector{ - "a", "b", "sea", "dee", " ", " ", "geee", "(づ。◕‿‿◕。)づ"}}})) { + if (!(res2.session_options == + std::map{ + {"foolong", 123L}, + {"bardouble", 456.0}, + {"big_ol_string_list", + std::vector{"a", "b", "sea", "dee", " ", " ", "geee", + "(づ。◕‿‿◕。)づ"}}})) { return Status::Invalid("res2 incorrect: " + res2.ToString()); } // Update - ARROW_ASSIGN_OR_RAISE(auto res3, client.SetSessionOptions({}, SetSessionOptionsRequest{{ - {"foolong", std::monostate{}}, - {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"} - }})); + ARROW_ASSIGN_OR_RAISE( + auto res3, + client.SetSessionOptions( + {}, SetSessionOptionsRequest{ + {{"foolong", std::monostate{}}, + {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}}})); ARROW_ASSIGN_OR_RAISE(auto res4, client.GetSessionOptions({}, {})); - if (!(res4.session_options == std::map{ - {"bardouble", 456.0}, - {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}})) { + if (!(res4.session_options == + std::map{ + {"bardouble", 456.0}, + {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}})) { return Status::Invalid("res4 incorrect: " + res4.ToString()); } diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.cc b/cpp/src/arrow/flight/sql/server_session_middleware.cc index 27c4b140ed89c..f3e02de232444 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.cc +++ b/cpp/src/arrow/flight/sql/server_session_middleware.cc @@ -42,8 +42,7 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { ServerSessionMiddlewareImpl(ServerSessionMiddlewareFactory* factory, const CallHeaders& headers, std::shared_ptr session, - std::string session_id, - bool existing_session = true) + std::string session_id, bool existing_session = true) : factory_(factory), headers_(headers), session_(std::move(session)), @@ -57,7 +56,8 @@ class ServerSessionMiddlewareImpl : public ServerSessionMiddleware { } if (!closed_session_id_.empty()) { add_call_headers->AddHeader( - "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_ + "; Max-Age=0"); + "set-cookie", static_cast(kSessionCookieName) + "=" + session_id_ + + "; Max-Age=0"); } } @@ -220,7 +220,7 @@ std::map FlightSession::GetSessionOptions() { } void FlightSession::SetSessionOption(const std::string& name, - const SessionOptionValue value) { + const SessionOptionValue value) { const std::lock_guard l(map_lock_); map_[name] = std::move(value); } From 5f6098162fdf604197f937270128689820a35f01 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 24 Jan 2024 15:05:42 -0800 Subject: [PATCH 179/195] Docstring --- cpp/src/arrow/flight/sql/server_session_middleware.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cpp/src/arrow/flight/sql/server_session_middleware.h b/cpp/src/arrow/flight/sql/server_session_middleware.h index 66a5bc28d65d8..021793de3de32 100644 --- a/cpp/src/arrow/flight/sql/server_session_middleware.h +++ b/cpp/src/arrow/flight/sql/server_session_middleware.h @@ -55,6 +55,9 @@ class ARROW_FLIGHT_SQL_EXPORT FlightSession { }; /// \brief A middleware to handle session option persistence and related cookie headers. +/// +/// WARNING that client cookie invalidation does not currently work due to a gRPC +/// transport bug. class ARROW_FLIGHT_SQL_EXPORT ServerSessionMiddleware : public ServerMiddleware { public: static constexpr char const kMiddlewareName[] = From 9f6c024e332c0f8d57b6c50b99f931e89b791bff Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Wed, 24 Jan 2024 15:07:06 -0800 Subject: [PATCH 180/195] Fix CMake lint error --- cpp/src/arrow/flight/sql/CMakeLists.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cpp/src/arrow/flight/sql/CMakeLists.txt b/cpp/src/arrow/flight/sql/CMakeLists.txt index 3cf0bd17fe4a4..b32f731496749 100644 --- a/cpp/src/arrow/flight/sql/CMakeLists.txt +++ b/cpp/src/arrow/flight/sql/CMakeLists.txt @@ -105,9 +105,8 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES) example/sqlite_server.cc example/sqlite_tables_schema_batch_reader.cc) - set(ARROW_FLIGHT_SQL_TEST_SRCS - server_test.cc - server_session_middleware_internals_test.cc) + set(ARROW_FLIGHT_SQL_TEST_SRCS server_test.cc + server_session_middleware_internals_test.cc) set(ARROW_FLIGHT_SQL_TEST_LIBS ${SQLite3_LIBRARIES}) set(ARROW_FLIGHT_SQL_ACERO_SRCS example/acero_server.cc) From 91fb77d491294390ce384161a58230842c17e23c Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Sun, 28 Jan 2024 17:06:51 -0800 Subject: [PATCH 181/195] [Java builds & passes] Remove Java integration tests that won't work with broken C++ --- .../tests/SessionOptionsScenario.java | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index 8a390e3ae689b..95c414150764b 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -17,11 +17,8 @@ package org.apache.arrow.flight.integration.tests; -import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.arrow.flight.CloseSessionRequest; -import org.apache.arrow.flight.CloseSessionResult; import org.apache.arrow.flight.FlightClient; import org.apache.arrow.flight.FlightProducer; import org.apache.arrow.flight.FlightRuntimeException; @@ -65,10 +62,6 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig try (final FlightClient flightClient = FlightClient.builder(allocator, location).intercept(factory).build()) { final FlightSqlClient client = new FlightSqlClient(flightClient); - // No existing session yet - IntegrationAssertions.assertThrows(FlightRuntimeException.class, - () -> client.getSessionOptions(new GetSessionOptionsRequest())); - // Set SetSessionOptionsRequest req1 = new SetSessionOptionsRequest(ImmutableMap.builder() .put("foolong", SessionOptionValueFactory.makeSessionOptionValue(123L)) @@ -110,18 +103,6 @@ public void client(BufferAllocator allocator, Location location, FlightClient ig SessionOptionValueFactory.makeSessionOptionValue("a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ")) .build(), res4.getSessionOptions()); - // Close - CloseSessionResult res5 = client.closeSession(new CloseSessionRequest()); - IntegrationAssertions.assertEquals(CloseSessionResult.Status.CLOSED, res5.getStatus()); - // Session should be defunct and cookie expired from cookie jar. - IntegrationAssertions.assertThrows(FlightRuntimeException.class, - () -> client.getSessionOptions(new GetSessionOptionsRequest())); - // This should create a new, empty session - SetSessionOptionsResult res6 = - client.setSessionOptions(new SetSessionOptionsRequest(new HashMap())); - GetSessionOptionsResult res7 = client.getSessionOptions(new GetSessionOptionsRequest()); - // This should be empty to confirm we have a new session, not reusing the same one somehow - IntegrationAssertions.assertEquals(new HashMap(), res7.getSessionOptions()); } } } From 4aa5b3cc7c856481f3c19cdcc9c308c09474a8fa Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 29 Jan 2024 10:07:06 -0800 Subject: [PATCH 182/195] Add docs --- cpp/src/arrow/flight/client.h | 2 +- docs/source/format/FlightSql.rst | 39 +++++++++++++++++++ .../arrow/flight/sql/FlightSqlProducer.java | 3 +- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/client.h b/cpp/src/arrow/flight/client.h index eb84699e5db55..330fa8bad730d 100644 --- a/cpp/src/arrow/flight/client.h +++ b/cpp/src/arrow/flight/client.h @@ -383,7 +383,7 @@ class ARROW_FLIGHT_EXPORT FlightClient { return DoExchange({}, descriptor); } - /// \brief Set server session option(s) by key/value. Sessions are generally + /// \brief Set server session option(s) by name/value. Sessions are generally /// persisted via HTTP cookies. /// \param[in] options Per-RPC options /// \param[in] request The server session options to set diff --git a/docs/source/format/FlightSql.rst b/docs/source/format/FlightSql.rst index add044c2d3621..a24fbabdcc508 100644 --- a/docs/source/format/FlightSql.rst +++ b/docs/source/format/FlightSql.rst @@ -170,6 +170,45 @@ the ``type`` should be ``ClosePreparedStatement``). When used with DoPut: execute the query and return the number of affected rows. +Flight Server Session Management +-------------------------------- + +Flight SQL provides commands to set and update server session variables +which affect the server behaviour in various ways. Common options may +include (depending on the server implementation) ``catalog`` and +``schema``, indicating the currently-selected catalog and schema for +queries to be run against. + +Clients should prefer, where possible, setting options prior to issuing +queries and other commands, as some server implementations may require +these options be set exactly once and prior to any other activity which +may trigger their implicit setting. + +For compatibility with Database Connectivity drivers (JDBC, ODBC, and +others), it is strongly recommended that server implementations accept +string representations of all option values which may be provided to the +driver as part of a server connection string and passed through to the +server without further conversion. For ease of use it is also recommended +to accept and convert other numeric types to the preferred type for an +option value, however this is not required. + +Sessions are persisted between the client and server using an +implementation-defined mechanism, which is typically RFC 6265 cookies. +Servers may also combine other connection state opaquely with the +session token: Consider that the lifespan and semantics of a session +should make sense for any additional uses, e.g. CloseSession would also +invalidate any authentication context persisted via the session context. + +``SetSessionOptions`` +Set server session option(s) by name/value. + +``GetSessionOptions`` +Get the current server session options, including those set by the client +and any defaulted or implicitly set by the server. + +``CloseSession`` +Close and invalidate the current session context. + Sequence Diagrams ================= diff --git a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java index 0d6ee782fd70f..f06c1b868f4fd 100644 --- a/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java +++ b/java/flight/flight-sql/src/main/java/org/apache/arrow/flight/sql/FlightSqlProducer.java @@ -517,7 +517,8 @@ public void onCompleted() { /** * Set server session options(s). * - * @param request The SetSessionOptionsRequest to set options from. + * @param request The session options to set. For *DBC driver compatibility, servers + * should support converting values from strings. * @param context Per-call context. * @param listener An interface for sending data back to the client. */ From 20286a199422c62aec696b19c7dccd6bf876e20c Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 29 Jan 2024 10:14:27 -0800 Subject: [PATCH 183/195] Add session_options to Archery integration testing --- dev/archery/archery/integration/runner.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dev/archery/archery/integration/runner.py b/dev/archery/archery/integration/runner.py index 299983f62f283..3525ae0be56a5 100644 --- a/dev/archery/archery/integration/runner.py +++ b/dev/archery/archery/integration/runner.py @@ -608,6 +608,11 @@ def run_all_tests(with_cpp=True, with_java=True, with_js=True, "RenewFlightEndpoint are working as expected."), skip_testers={"JS", "C#", "Rust"}, ), + Scenario( + "session_options", + description="Ensure Flight SQL Sessions work as expected.", + skip_testers={"JS", "C#", "Rust"} + ), Scenario( "poll_flight_info", description="Ensure PollFlightInfo is supported.", From b71edf55cc65835468825e3c99afcbb6349dc3f0 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 29 Jan 2024 10:29:25 -0800 Subject: [PATCH 184/195] Fix imports --- .../arrow/flight/integration/tests/SessionOptionsScenario.java | 1 - 1 file changed, 1 deletion(-) diff --git a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java index 95c414150764b..c150cfa6ef137 100644 --- a/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java +++ b/java/flight/flight-integration-tests/src/main/java/org/apache/arrow/flight/integration/tests/SessionOptionsScenario.java @@ -21,7 +21,6 @@ import org.apache.arrow.flight.FlightClient; import org.apache.arrow.flight.FlightProducer; -import org.apache.arrow.flight.FlightRuntimeException; import org.apache.arrow.flight.FlightServer; import org.apache.arrow.flight.FlightServerMiddleware; import org.apache.arrow.flight.GetSessionOptionsRequest; From 1078d47bb1f8665bfe9ac4c783c264883c26aab8 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 29 Jan 2024 11:45:48 -0800 Subject: [PATCH 185/195] Exclude session_options go test --- dev/archery/archery/integration/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/archery/archery/integration/runner.py b/dev/archery/archery/integration/runner.py index 3525ae0be56a5..e984468bc5052 100644 --- a/dev/archery/archery/integration/runner.py +++ b/dev/archery/archery/integration/runner.py @@ -611,7 +611,7 @@ def run_all_tests(with_cpp=True, with_java=True, with_js=True, Scenario( "session_options", description="Ensure Flight SQL Sessions work as expected.", - skip_testers={"JS", "C#", "Rust"} + skip_testers={"JS", "C#", "Rust", "Go"} ), Scenario( "poll_flight_info", From 07ac419d6ad49e92231143eb49a7631570fda0e5 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 29 Jan 2024 12:00:33 -0800 Subject: [PATCH 186/195] Docs touchup --- docs/source/format/FlightSql.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/format/FlightSql.rst b/docs/source/format/FlightSql.rst index a24fbabdcc508..6bb917271366c 100644 --- a/docs/source/format/FlightSql.rst +++ b/docs/source/format/FlightSql.rst @@ -198,6 +198,8 @@ Servers may also combine other connection state opaquely with the session token: Consider that the lifespan and semantics of a session should make sense for any additional uses, e.g. CloseSession would also invalidate any authentication context persisted via the session context. +A session may be initiated upon a nonempty (or empty) SetSessionOptions +call, or at any other time of the server's choosing. ``SetSessionOptions`` Set server session option(s) by name/value. From 270c1524c317aa1164ddff145834ff4cb6717a4a Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 30 Jan 2024 15:01:59 -0800 Subject: [PATCH 187/195] [Builds & passes] naming consistency fix --- cpp/src/arrow/flight/serialization_internal.cc | 8 ++++---- format/Flight.proto | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/src/arrow/flight/serialization_internal.cc b/cpp/src/arrow/flight/serialization_internal.cc index 607faeee77eed..10600d055b3a8 100644 --- a/cpp/src/arrow/flight/serialization_internal.cc +++ b/cpp/src/arrow/flight/serialization_internal.cc @@ -441,16 +441,16 @@ Status FromProto(const google::protobuf::Map& map, google::protobuf::Map* pb_map) { - for (const auto& [key, val] : map) { - RETURN_NOT_OK(ToProto(val, &(*pb_map)[key])); + for (const auto& [name, val] : map) { + RETURN_NOT_OK(ToProto(val, &(*pb_map)[name])); } return Status::OK(); } diff --git a/format/Flight.proto b/format/Flight.proto index d0a661ae8bd4a..55a99a5a2a8f8 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -568,7 +568,7 @@ message SetSessionOptionsRequest { * EXPERIMENTAL: The results (individually) of setting a set of session options. * * Option names should only be present in the response if they were not successfully - * set on the server; that is, a response without an Error for a key provided in the + * set on the server; that is, a response without an Error for a name provided in the * SetSessionOptionsRequest implies that the named option value was set successfully. */ message SetSessionOptionsResult { From a1d19dcc667f8363c2001a3ead98feeffdd2ad3a Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Tue, 30 Jan 2024 15:11:45 -0800 Subject: [PATCH 188/195] [Builds & passes] Docstring fixups --- .../java/org/apache/arrow/flight/FlightClient.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java index 3073c6339d17c..980a762e397f9 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/FlightClient.java @@ -581,7 +581,9 @@ public FlightEndpoint renewFlightEndpoint(RenewFlightEndpointRequest request, Ca } /** - * Request the server to extend the lifetime of a query result set. + * Set server session option(s) by name/value. + * + * Sessions are generally persisted via HTTP cookies. * * @param request The session options to set on the server. * @param options Call options. @@ -611,7 +613,9 @@ public SetSessionOptionsResult setSessionOptions(SetSessionOptionsRequest reques } /** - * Request the server to extend the lifetime of a query result set. + * Get the current server session options. + * + * The session is generally accessed via an HTTP cookie. * * @param request The (empty) GetSessionOptionsRequest. * @param options Call options. @@ -641,7 +645,9 @@ public GetSessionOptionsResult getSessionOptions(GetSessionOptionsRequest reques } /** - * Request the server to extend the lifetime of a query result set. + * Close/invalidate the current server session. + * + * The session is generally accessed via an HTTP cookie. * * @param request The (empty) CloseSessionRequest. * @param options Call options. From 33d66c4dcd158171d0c67350a315a9b09889864d Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 5 Feb 2024 10:57:05 -0800 Subject: [PATCH 189/195] Address PR feedback --- .../flight/integration_tests/test_integration.cc | 16 ++++++++-------- format/Flight.proto | 5 ++--- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index d156bad200279..2e0460b403938 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -799,8 +799,8 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { arrow::Result GetSessionOptions( const ServerCallContext& context, const GetSessionOptionsRequest& request) override { - sql::ServerSessionMiddleware* middleware = - (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + auto* middleware = static_cast( + context.GetMiddleware(session_middleware_key)); if (!middleware->HasSession()) { return Status::Invalid("No existing session to get options from."); } @@ -857,24 +857,24 @@ class SessionOptionsScenario : public Scenario { " ", "geee", "(づ。◕‿‿◕。)づ"}}}}; ARROW_ASSIGN_OR_RAISE(auto res1, client.SetSessionOptions({}, req1)); // Some errors - if (!(res1.errors == + if (res1.errors != std::map{ {"lol_invalid", SetSessionOptionsResult::Error{SetSessionOptionErrorValue::kInvalidName}}, {"key_with_invalid_value", SetSessionOptionsResult::Error{ - SetSessionOptionErrorValue::kInvalidValue}}})) { + SetSessionOptionErrorValue::kInvalidValue}}}) { return Status::Invalid("res1 incorrect: " + res1.ToString()); } // Some set, some omitted due to above errors ARROW_ASSIGN_OR_RAISE(auto res2, client.GetSessionOptions({}, {})); - if (!(res2.session_options == + if (res2.session_options != std::map{ {"foolong", 123L}, {"bardouble", 456.0}, {"big_ol_string_list", std::vector{"a", "b", "sea", "dee", " ", " ", "geee", - "(づ。◕‿‿◕。)づ"}}})) { + "(づ。◕‿‿◕。)づ"}}}) { return Status::Invalid("res2 incorrect: " + res2.ToString()); } // Update @@ -885,10 +885,10 @@ class SessionOptionsScenario : public Scenario { {{"foolong", std::monostate{}}, {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}}})); ARROW_ASSIGN_OR_RAISE(auto res4, client.GetSessionOptions({}, {})); - if (!(res4.session_options == + if (res4.session_options != std::map{ {"bardouble", 456.0}, - {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}})) { + {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}}) { return Status::Invalid("res4 incorrect: " + res4.ToString()); } diff --git a/format/Flight.proto b/format/Flight.proto index 55a99a5a2a8f8..f2d7fc4e43b6c 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -573,9 +573,8 @@ message SetSessionOptionsRequest { */ message SetSessionOptionsResult { enum ErrorValue { - // The status of setting the option is unknown. Servers should avoid using - // this value (send a NOT_FOUND error if the requested query is - // not known). Clients can retry the request. + // The status is unknown or unrecognized. Servers should avoid using this value. The + // request may be retried by the client. UNSPECIFIED = 0; // The given session option name is invalid. INVALID_NAME = 1; From 591281a65b4b93a56586fae394cac3e8d90701cf Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 5 Feb 2024 11:15:55 -0800 Subject: [PATCH 190/195] Update Protobuf enum comments --- format/Flight.proto | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/format/Flight.proto b/format/Flight.proto index f2d7fc4e43b6c..59714108e1cbc 100644 --- a/format/Flight.proto +++ b/format/Flight.proto @@ -573,8 +573,8 @@ message SetSessionOptionsRequest { */ message SetSessionOptionsResult { enum ErrorValue { - // The status is unknown or unrecognized. Servers should avoid using this value. The - // request may be retried by the client. + // Protobuf deserialization fallback value: The status is unknown or unrecognized. + // Servers should avoid using this value. The request may be retried by the client. UNSPECIFIED = 0; // The given session option name is invalid. INVALID_NAME = 1; @@ -594,9 +594,10 @@ message SetSessionOptionsResult { /* * EXPERIMENTAL: A request to access the session options for the current server session. * - * The existing session is referenced via a cookie header or similar (see SetSessionOptionsRequest - * above); it is an error to make this request with a missing, invalid, or expired session cookie - * header or other implementation-defined session reference token. + * The existing session is referenced via a cookie header or similar (see + * SetSessionOptionsRequest above); it is an error to make this request with a missing, + * invalid, or expired session cookie header or other implementation-defined session + * reference token. */ message GetSessionOptionsRequest { } @@ -621,9 +622,9 @@ message CloseSessionRequest { */ message CloseSessionResult { enum Status { - // The session close status is unknown. Servers should avoid using - // this value (send a NOT_FOUND error if the requested session is - // not known). Clients can retry the request. + // Protobuf deserialization fallback value: The session close status is unknown or + // not recognized. Servers should avoid using this value (send a NOT_FOUND error if + // the requested session is not known or expired). Clients can retry the request. UNSPECIFIED = 0; // The session close request is complete. Subsequent requests with // the same session produce a NOT_FOUND error. From 58381baa99480f7c4243a85c5855f6bf3e980084 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Mon, 5 Feb 2024 12:29:24 -0800 Subject: [PATCH 191/195] Linter fixups & rebase --- .../integration_tests/test_integration.cc | 29 +++++++++---------- .../arrow/flight/CloseSessionRequest.java | 6 ++-- .../flight/GetSessionOptionsRequest.java | 6 ++-- .../arrow/flight/SessionOptionValue.java | 3 +- testing | 2 +- 5 files changed, 25 insertions(+), 21 deletions(-) diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index 2e0460b403938..06d958d266b80 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -858,23 +858,22 @@ class SessionOptionsScenario : public Scenario { ARROW_ASSIGN_OR_RAISE(auto res1, client.SetSessionOptions({}, req1)); // Some errors if (res1.errors != - std::map{ - {"lol_invalid", - SetSessionOptionsResult::Error{SetSessionOptionErrorValue::kInvalidName}}, - {"key_with_invalid_value", - SetSessionOptionsResult::Error{ - SetSessionOptionErrorValue::kInvalidValue}}}) { + std::map{ + {"lol_invalid", + SetSessionOptionsResult::Error{SetSessionOptionErrorValue::kInvalidName}}, + {"key_with_invalid_value", SetSessionOptionsResult::Error{ + SetSessionOptionErrorValue::kInvalidValue}}}) { return Status::Invalid("res1 incorrect: " + res1.ToString()); } // Some set, some omitted due to above errors ARROW_ASSIGN_OR_RAISE(auto res2, client.GetSessionOptions({}, {})); if (res2.session_options != - std::map{ - {"foolong", 123L}, - {"bardouble", 456.0}, - {"big_ol_string_list", - std::vector{"a", "b", "sea", "dee", " ", " ", "geee", - "(づ。◕‿‿◕。)づ"}}}) { + std::map{ + {"foolong", 123L}, + {"bardouble", 456.0}, + {"big_ol_string_list", + std::vector{"a", "b", "sea", "dee", " ", " ", "geee", + "(づ。◕‿‿◕。)づ"}}}) { return Status::Invalid("res2 incorrect: " + res2.ToString()); } // Update @@ -886,9 +885,9 @@ class SessionOptionsScenario : public Scenario { {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}}})); ARROW_ASSIGN_OR_RAISE(auto res4, client.GetSessionOptions({}, {})); if (res4.session_options != - std::map{ - {"bardouble", 456.0}, - {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}}) { + std::map{ + {"bardouble", 456.0}, + {"big_ol_string_list", "a,b,sea,dee, , ,geee,(づ。◕‿‿◕。)づ"}}) { return Status::Invalid("res4 incorrect: " + res4.ToString()); } diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java index e700b73e652bc..29eb3664f6286 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/CloseSessionRequest.java @@ -24,9 +24,11 @@ /** A request to close/invalidate a server session context. */ public class CloseSessionRequest { - public CloseSessionRequest() {} + public CloseSessionRequest() { + } - CloseSessionRequest(Flight.CloseSessionRequest proto) {} + CloseSessionRequest(Flight.CloseSessionRequest proto) { + } Flight.CloseSessionRequest toProtocol() { return Flight.CloseSessionRequest.getDefaultInstance(); diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java index 4c40260d50044..9d63e59027aac 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/GetSessionOptionsRequest.java @@ -26,9 +26,11 @@ * A request to get current session options. */ public class GetSessionOptionsRequest { - public GetSessionOptionsRequest() {} + public GetSessionOptionsRequest() { + } - GetSessionOptionsRequest(Flight.GetSessionOptionsRequest proto) {} + GetSessionOptionsRequest(Flight.GetSessionOptionsRequest proto) { + } Flight.GetSessionOptionsRequest toProtocol() { return Flight.GetSessionOptionsRequest.getDefaultInstance(); diff --git a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java index bc4aecc352030..db22c736be182 100644 --- a/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java +++ b/java/flight/flight-core/src/main/java/org/apache/arrow/flight/SessionOptionValue.java @@ -25,7 +25,8 @@ * A union-like container interface for supported session option value types. */ public abstract class SessionOptionValue { - SessionOptionValue() {} + SessionOptionValue() { + } /** * Value access via a caller-provided visitor/functor. diff --git a/testing b/testing index 25d16511e8d42..ad82a736c170e 160000 --- a/testing +++ b/testing @@ -1 +1 @@ -Subproject commit 25d16511e8d42c2744a1d94d90169e3a36e92631 +Subproject commit ad82a736c170e97b7c8c035ebd8a801c17eec170 From 042a1934794f6cc40bca8ee261dca594c03e9576 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 9 Feb 2024 17:04:10 -0800 Subject: [PATCH 192/195] Factor out addMiddlewareHeaders --- .../flight/transport/grpc/grpc_server.cc | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/cpp/src/arrow/flight/transport/grpc/grpc_server.cc b/cpp/src/arrow/flight/transport/grpc/grpc_server.cc index bbd01155fe4a4..07ba519df314f 100644 --- a/cpp/src/arrow/flight/transport/grpc/grpc_server.cc +++ b/cpp/src/arrow/flight/transport/grpc/grpc_server.cc @@ -290,7 +290,8 @@ class GrpcServiceHandler final : public FlightService::Service { // Authenticate the client (if applicable) and construct the call context ::grpc::Status CheckAuth(const FlightMethod& method, ServerContext* context, - GrpcServerCallContext& flight_context) { + GrpcServerCallContext& flight_context, + bool skip_headers = false) { if (!auth_handler_) { const auto auth_context = context->auth_context(); if (auth_context && auth_context->IsPeerAuthenticated()) { @@ -320,11 +321,11 @@ class GrpcServiceHandler final : public FlightService::Service { // Authenticate the client (if applicable) and construct the call context ::grpc::Status MakeCallContext(const FlightMethod& method, ServerContext* context, - GrpcServerCallContext& flight_context) { + GrpcServerCallContext& flight_context, + bool skip_headers = false) { // Run server middleware const CallInfo info{method}; - GrpcAddServerHeaders outgoing_headers(context); for (const auto& factory : middleware_) { std::shared_ptr instance; Status result = factory.second->StartCall(info, flight_context, &instance); @@ -336,13 +337,25 @@ class GrpcServiceHandler final : public FlightService::Service { if (instance != nullptr) { flight_context.middleware_.push_back(instance); flight_context.middleware_map_.insert({factory.first, instance}); - instance->SendingHeaders(&outgoing_headers); } } + // TODO factor this out after fixing all streaming and non-streaming handlers + if (!skip_headers) { + addMiddlewareHeaders(context, flight_context); + } + return ::grpc::Status::OK; } + void addMiddlewareHeaders(ServerContext* context, + GrpcServerCallContext& flight_context) { + GrpcAddServerHeaders outgoing_headers(context); + for (const std::shared_ptr& instance : flight_context.middleware_) { + instance->SendingHeaders(&outgoing_headers); + } + } + ::grpc::Status Handshake( ServerContext* context, ::grpc::ServerReaderWriter* stream) { From 60c129875fc30ea7b1ac0a8e2ce604aecef68122 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Fri, 9 Feb 2024 17:09:15 -0800 Subject: [PATCH 193/195] Refactor GrpcServiceHandler::GetFlightInfo() to use addMiddlewareHeaders() --- cpp/src/arrow/flight/transport/grpc/grpc_server.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cpp/src/arrow/flight/transport/grpc/grpc_server.cc b/cpp/src/arrow/flight/transport/grpc/grpc_server.cc index 07ba519df314f..a9780b5eeb77e 100644 --- a/cpp/src/arrow/flight/transport/grpc/grpc_server.cc +++ b/cpp/src/arrow/flight/transport/grpc/grpc_server.cc @@ -412,8 +412,9 @@ class GrpcServiceHandler final : public FlightService::Service { SERVICE_RETURN_NOT_OK(flight_context, internal::FromProto(*request, &descr)); std::unique_ptr info; - SERVICE_RETURN_NOT_OK(flight_context, - impl_->base()->GetFlightInfo(flight_context, descr, &info)); + auto res = impl_->base()->GetFlightInfo(flight_context, descr, &info); + addMiddlewareHeaders(context, flight_context); + SERVICE_RETURN_NOT_OK(flight_context, res); if (!info) { // Treat null listing as no flights available From f80b94183162e675e2d8d89cf6caebeb562b01b2 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 15 Feb 2024 13:06:58 -0800 Subject: [PATCH 194/195] PR feedback --- .../arrow/flight/integration_tests/test_integration.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index 06d958d266b80..85c079eea28ea 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -748,7 +748,7 @@ class ExpirationTimeRenewFlightEndpointScenario : public Scenario { /// \brief The server used for testing Session Options. /// -/// setSessionOptions has a blacklisted option name and string option value, +/// SetSessionOptions has a blacklisted option name and string option value, /// both "lol_invalid", which will result in errors attempting to set either. class SessionOptionsServer : public sql::FlightSqlServerBase { static inline const std::string invalid_option_name = "lol_invalid"; @@ -768,8 +768,8 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { const SetSessionOptionsRequest& request) override { SetSessionOptionsResult res; - sql::ServerSessionMiddleware* middleware = - (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + auto* middleware = static_cast( + context.GetMiddleware(session_middleware_key)); ARROW_ASSIGN_OR_RAISE(std::shared_ptr session, middleware->GetSession()); @@ -813,8 +813,8 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { arrow::Result CloseSession( const ServerCallContext& context, const CloseSessionRequest& request) override { // Broken (does not expire cookie) until C++ middleware SendingHeaders handling fixed. - sql::ServerSessionMiddleware* middleware = - (sql::ServerSessionMiddleware*)context.GetMiddleware(session_middleware_key); + auto* middleware = static_cast( + context.GetMiddleware(session_middleware_key)); ARROW_RETURN_NOT_OK(middleware->CloseSession()); return CloseSessionResult{CloseSessionStatus::kClosed}; } From 265e5e86226d97db5bc21932ed0eae0029ebb0a9 Mon Sep 17 00:00:00 2001 From: Paul Nienaber Date: Thu, 15 Feb 2024 13:10:51 -0800 Subject: [PATCH 195/195] PR feedback --- cpp/src/arrow/flight/integration_tests/test_integration.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/src/arrow/flight/integration_tests/test_integration.cc b/cpp/src/arrow/flight/integration_tests/test_integration.cc index 85c079eea28ea..d4e0a2cda5bd8 100644 --- a/cpp/src/arrow/flight/integration_tests/test_integration.cc +++ b/cpp/src/arrow/flight/integration_tests/test_integration.cc @@ -812,7 +812,7 @@ class SessionOptionsServer : public sql::FlightSqlServerBase { arrow::Result CloseSession( const ServerCallContext& context, const CloseSessionRequest& request) override { - // Broken (does not expire cookie) until C++ middleware SendingHeaders handling fixed. + // Broken (does not expire cookie) until C++ middleware handling (GH-39791) fixed: auto* middleware = static_cast( context.GetMiddleware(session_middleware_key)); ARROW_RETURN_NOT_OK(middleware->CloseSession());