You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by GitBox <gi...@apache.org> on 2021/10/21 16:06:17 UTC

[GitHub] [arrow] rafael-telles opened a new pull request #11507: [C++] Implement Flight SQL

rafael-telles opened a new pull request #11507:
URL: https://github.com/apache/arrow/pull/11507


   **Introduction**
   This experimental PR implements Flight SQL for C++, which formalizes SQL semantics on top of Flight. This follows the same functionalities as in the Java implementation (#10906)
   
   **An Overview of this PR**
   This PR adds a new module within Flight called flight-sql (located on `cpp/src/arrow/flight/flight-sql`).
   flight-sql is a new Flight API that provides a standard way for clients and servers to communicate with SQL-like semantics.
   Like other Flight APIs, flight-sql does not provide implementation details that dictate how a client and server communicates with each other, it simply provides the SQL semantics and apply them onto the Flight API.
   
   **A Walkthrough of the New Module**
   FlightSql.proto introduces new SQL protobuf objects (the same as in #10906).
   FlightSqlClient (client.h) introduces a new wrapper for a FlightClient that adds the Flight SQL semantics on the client side.
   FlightSqlServerBase (server.h) introduces a new FlightServerBase API that adapts classic Flight requests into SQL operations.
   SQLiteFlightSqlServer (example/sqlite_server.h) is a sample Flight SQL server implementation using an in-memory SQLite as the underlying database.
   
   FlightSqlClient is fully implemented. 
   FlightSqlServerBase and the example server are in progress (only missing the GetSqlInfo command) and will be finished very soon.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r733879318



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

Review comment:
       This looks unused here.

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"

Review comment:
       There's no new gRPC definitions, right? We don't need to generate gRPC sources (and we don't need to depend on grpc_cpp_plugin above)

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);

Review comment:
       Prefer `Result<int64_t>` over `Status` with out parameter for new code. (The Flight code predates the introduction of `Result`.)

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \param schema   The parameter schema from the query.
+  /// \return         Status.
+  Status GetParameterSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \param schema   The ResultSet schema from the query.
+  /// \return         Status.
+  Status GetResultSetSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding_   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.
+  /// \return Status.
+  Status Close();
+
+  /// \brief Checks if the prepared statement is closed.
+  /// \return The state of the prepared statement.
+  bool IsClosed() const;
+};
+
+/// \brief Flight client with Flight SQL semantics.
+template <class T = arrow::flight::FlightClient>
+class FlightSqlClientT {
+ public:
+  explicit FlightSqlClientT(std::unique_ptr<T>& client);

Review comment:
       This should just be `std::unique_ptr<T>` if the intent is to take ownership of the client.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,572 @@
+// 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/api.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/types.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+using internal::FlightSqlClientT;
+
+class FlightClientMock {
+ public:
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto* client_mock = new FlightClientMock();
+  std::unique_ptr<FlightClientMock> client_mock_ptr(client_mock);
+  FlightSqlClientT<FlightClientMock> sqlClient(client_mock_ptr);
+  FlightCallOptions call_options;
+
+  pb::sql::CommandGetCatalogs command;
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  std::unique_ptr<FlightInfo> flight_info;
+  EXPECT_CALL(*client_mock, GetFlightInfo(Ref(call_options), descriptor, &flight_info));
+
+  (void)sqlClient.GetCatalogs(call_options, &flight_info);
+}
+
+TEST(TestFlightSqlClient, TestGetSchemas) {
+  auto* client_mock = new FlightClientMock();
+  std::unique_ptr<FlightClientMock> client_mock_ptr(client_mock);
+  FlightSqlClientT<FlightClientMock> sqlClient(client_mock_ptr);
+  FlightCallOptions call_options;

Review comment:
       meta-comment: a test fixture to do this common setup would clean up these tests.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,572 @@
+// 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/api.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/types.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+using internal::FlightSqlClientT;
+
+class FlightClientMock {
+ public:
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto* client_mock = new FlightClientMock();
+  std::unique_ptr<FlightClientMock> client_mock_ptr(client_mock);
+  FlightSqlClientT<FlightClientMock> sqlClient(client_mock_ptr);
+  FlightCallOptions call_options;
+
+  pb::sql::CommandGetCatalogs command;
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  std::unique_ptr<FlightInfo> flight_info;
+  EXPECT_CALL(*client_mock, GetFlightInfo(Ref(call_options), descriptor, &flight_info));
+
+  (void)sqlClient.GetCatalogs(call_options, &flight_info);
+}
+
+TEST(TestFlightSqlClient, TestGetSchemas) {
+  auto* client_mock = new FlightClientMock();
+  std::unique_ptr<FlightClientMock> client_mock_ptr(client_mock);
+  FlightSqlClientT<FlightClientMock> sqlClient(client_mock_ptr);
+  FlightCallOptions call_options;
+
+  std::string schema_filter_pattern = "schema_filter_pattern";
+  std::string catalog = "catalog";
+
+  pb::sql::CommandGetSchemas command;
+  command.set_catalog(catalog);
+  command.set_schema_filter_pattern(schema_filter_pattern);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  std::unique_ptr<FlightInfo> flight_info;
+  EXPECT_CALL(*client_mock, GetFlightInfo(Ref(call_options), descriptor, &flight_info));
+
+  (void)sqlClient.GetSchemas(call_options, &catalog, &schema_filter_pattern,

Review comment:
       why not ASSERT_OK here?

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       Is the templating here just to support mocking the client?
   
   It's a little unfortunate, since the templating makes the API confusing + prevents us from being able to move definitions into a .cc file. I also think we shouldn't expose the Protobuf types publically everywhere. (The field is private, but the header still gets included…being able to pImpl this class would help.)

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+               STATIC_LINK_LIBS
+               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+               GTest::gtest
+               GTest::gmock
+               LABELS
+               "arrow_flight_sql")
+
+add_executable(flight_sql_test_app test_app_cli.cc

Review comment:
       I think we should guard these definitions behind ARROW_BUILD_TESTS or ARROW_BUILD_EXAMPLES or similar, so that we don't require everyone to have SQLite3 installed. 

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,404 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/server.h>
+#include <google/protobuf/any.pb.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlServerBase : public FlightServerBase {
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType FLIGHT_SQL_CREATE_PREPARED_STATEMENT =
+      ActionType{.type = "CreatePreparedStatement",
+                 .description =
+                     "Creates a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionCreatePreparedStatementRequest\n"
+                     "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType FLIGHT_SQL_CLOSE_PREPARED_STATEMENT =
+      ActionType{.type = "ClosePreparedStatement",
+                 .description =
+                     "Closes a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionClosePreparedStatementRequest\n"
+                     "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] command      The CommandStatementQuery object containing the SQL
+  ///                         statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const pb::sql::CommandStatementQuery& command,
+                                        const ServerCallContext& context,
+                                        const FlightDescriptor& descriptor,
+                                        std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the query results.
+  /// \param[in] command      The TicketStatementQuery containing the statement handle.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetStatement(const pb::sql::TicketStatementQuery& command,
+                                const ServerCallContext& context,
+                                std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for executing an already created prepared statement.
+  /// \param[in] command      The CommandPreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPreparedStatement(
+      const pb::sql::CommandPreparedStatementQuery& command,
+      const ServerCallContext& context, const FlightDescriptor& descriptor,
+      std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the prepared statement query results.
+  /// \param[in] command      The CommandPreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetPreparedStatement(
+      const pb::sql::CommandPreparedStatementQuery& command,
+      const ServerCallContext& context, std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for listing catalogs.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoCatalogs(const ServerCallContext& context,
+                                       const FlightDescriptor& descriptor,
+                                       std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of catalogs.
+  /// \param[in] context  Per-call context.
+  /// \param[out] result  An interface for sending data back to the client.
+  /// \return             Status.
+  virtual Status DoGetCatalogs(const ServerCallContext& context,
+                               std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for retrieving other information (See SqlInfo).
+  /// \param[in] command      The CommandGetSqlInfo object containing the list of SqlInfo
+  ///                         to be returned.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoSqlInfo(const pb::sql::CommandGetSqlInfo& command,
+                                      const ServerCallContext& context,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of SqlInfo results.
+  /// \param[in] command    The CommandGetSqlInfo object containing the list of SqlInfo
+  ///                       to be returned.
+  /// \param[in] context    Per-call context.
+  /// \param[out] result    The FlightDataStream containing the results.
+  /// \return               Status.
+  virtual Status DoGetSqlInfo(const pb::sql::CommandGetSqlInfo& command,
+                              const ServerCallContext& context,
+                              std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for listing schemas.
+  /// \param[in] command      The CommandGetSchemas object which may contain filters for
+  ///                         catalog and schema name.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoSchemas(const pb::sql::CommandGetSchemas& command,
+                                      const ServerCallContext& context,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of schemas.
+  /// \param[in] command   The CommandGetSchemas object which may contain filters for
+  ///                      catalog and schema name.
+  /// \param[in] context   Per-call context.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return              Status.
+  virtual Status DoGetSchemas(const pb::sql::CommandGetSchemas& command,
+                              const ServerCallContext& context,
+                              std::unique_ptr<FlightDataStream>* result);
+
+  ///\brief Gets a FlightInfo for listing tables.
+  /// \param[in] command      The CommandGetTables object which may contain filters for
+  ///                         catalog, schema and table names.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoTables(const pb::sql::CommandGetTables& command,
+                                     const ServerCallContext& context,
+                                     const FlightDescriptor& descriptor,
+                                     std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of tables.
+  /// \param[in] command   The CommandGetTables object which may contain filters for
+  ///                      catalog, schema and table names.
+  /// \param[in] context   Per-call context.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return              Status.
+  virtual Status DoGetTables(const pb::sql::CommandGetTables& command,
+                             const ServerCallContext& context,
+                             std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about the table types.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoTableTypes(const ServerCallContext& context,
+                                         const FlightDescriptor& descriptor,
+                                         std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the table types.
+  /// \param[in] context   Per-call context.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return               Status.
+  virtual Status DoGetTableTypes(const ServerCallContext& context,
+                                 std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about primary and foreign keys.
+  /// \param[in] command      The CommandGetPrimaryKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPrimaryKeys(const pb::sql::CommandGetPrimaryKeys& command,
+                                          const ServerCallContext& context,
+                                          const FlightDescriptor& descriptor,
+                                          std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the primary and
+  /// foreign
+  ///        keys.
+  /// \param[in] command  The CommandGetPrimaryKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[in] context  Per-call context.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetPrimaryKeys(const pb::sql::CommandGetPrimaryKeys& command,
+                                  const ServerCallContext& context,
+                                  std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] command      The CommandGetExportedKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoExportedKeys(const pb::sql::CommandGetExportedKeys& command,
+                                           const ServerCallContext& context,
+                                           const FlightDescriptor& descriptor,
+                                           std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  /// primary
+  ///        keys.
+  /// \param[in] command  The CommandGetExportedKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[in] context  Per-call context.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetExportedKeys(const pb::sql::CommandGetExportedKeys& command,
+                                   const ServerCallContext& context,
+                                   std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] command      The CommandGetImportedKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoImportedKeys(const pb::sql::CommandGetImportedKeys& command,
+                                           const ServerCallContext& context,
+                                           const FlightDescriptor& descriptor,
+                                           std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  ///        primary keys.
+  /// \param[in] command  The CommandGetImportedKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[in] context  Per-call context.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetImportedKeys(const pb::sql::CommandGetImportedKeys& command,
+                                   const ServerCallContext& context,
+                                   std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] command      The CommandGetCrossReference object with necessary
+  /// information
+  ///                         to execute the request.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoCrossReference(
+      const pb::sql::CommandGetCrossReference& command, const ServerCallContext& context,
+      const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  ///        primary keys.
+  /// \param[in] command  The CommandGetCrossReference object with necessary information
+  ///                     to execute the request.
+  /// \param[in] context  Per-call context.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetCrossReference(const pb::sql::CommandGetCrossReference& command,
+                                     const ServerCallContext& context,
+                                     std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Executes an update SQL statement.
+  /// \param[in] command  The CommandStatementUpdate object containing the SQL statement.
+  /// \param[in] context  The call context.
+  /// \param[in] reader   a sequence of uploaded record batches.
+  /// \param[in] writer   send metadata back to the client.
+  /// \return             Status.
+  virtual Status DoPutCommandStatementUpdate(
+      const pb::sql::CommandStatementUpdate& command, const ServerCallContext& context,
+      std::unique_ptr<FlightMessageReader>& reader,
+      std::unique_ptr<FlightMetadataWriter>& writer);
+
+  /// \brief Create a prepared statement from given SQL statement.
+  /// \param[in] request  The ActionCreatePreparedStatementRequest object containing the
+  ///                     SQL statement.
+  /// \param[in] context  The call context.
+  /// \param[out] result  ResultStream containing a ActionCreatePreparedStatementResult.
+  virtual Status CreatePreparedStatement(
+      const pb::sql::ActionCreatePreparedStatementRequest& request,
+      const ServerCallContext& context, std::unique_ptr<ResultStream>* result);
+
+  /// \brief Closes a prepared statement.
+  /// \param[in] request  The ActionClosePreparedStatementRequest object containing the
+  ///                     prepared statement handle.
+  /// \param[in] context  The call context.
+  /// \param[out] result  Empty ResultStream.
+  virtual Status ClosePreparedStatement(
+      const pb::sql::ActionClosePreparedStatementRequest& request,
+      const ServerCallContext& context, std::unique_ptr<ResultStream>* result);
+
+  /// \brief Binds parameters to given prepared statement.
+  /// \param[in] command  The CommandPreparedStatementQuery object containing the
+  ///                     prepared statement handle.
+  /// \param[in] context  The call context.
+  /// \param[in] reader   A sequence of uploaded record batches.
+  /// \param[in] writer   Send metadata back to the client.
+  virtual Status DoPutPreparedStatementQuery(
+      const pb::sql::CommandPreparedStatementQuery& command,
+      const ServerCallContext& context, std::unique_ptr<FlightMessageReader>& reader,
+      std::unique_ptr<FlightMetadataWriter>& writer);
+
+  /// \brief Executes an update SQL prepared statement.
+  /// \param[in] command  The CommandPreparedStatementUpdate object containing the
+  ///                     prepared statement handle.
+  /// \param[in] context  The call context.
+  /// \param[in] reader   a sequence of uploaded record batches.
+  /// \param[in] writer   send metadata back to the client.
+  /// \return             Status.
+  virtual Status DoPutPreparedStatementUpdate(
+      const pb::sql::CommandPreparedStatementUpdate& command,
+      const ServerCallContext& context, std::unique_ptr<FlightMessageReader>& reader,
+      std::unique_ptr<FlightMetadataWriter>& writer);
+};
+
+/// \brief Auxiliary class containing all Schemas used on Flight SQL.
+class SqlSchema {

Review comment:
       This should probably still be declared ARROW_EXPORT.
   
   Though, given this is C++, we could just make all of these top-level functions.
   

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \

Review comment:
       There's MakeArrayOfNull for this use case too.

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,404 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/server.h>
+#include <google/protobuf/any.pb.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlServerBase : public FlightServerBase {
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType FLIGHT_SQL_CREATE_PREPARED_STATEMENT =
+      ActionType{.type = "CreatePreparedStatement",
+                 .description =
+                     "Creates a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionCreatePreparedStatementRequest\n"
+                     "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType FLIGHT_SQL_CLOSE_PREPARED_STATEMENT =
+      ActionType{.type = "ClosePreparedStatement",
+                 .description =
+                     "Closes a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionClosePreparedStatementRequest\n"
+                     "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] command      The CommandStatementQuery object containing the SQL
+  ///                         statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const pb::sql::CommandStatementQuery& command,

Review comment:
       I don't think we've talked about whether to wrap the Protobufs before or not, now that I think about it. The Java PR passes them through to the server, as does this PR. While Flight itself wraps its Protobufs, I would say it's not too bad here given FlightSql is defined in terms of Protobuf. But it might be good to wrap these regardless to avoid leaking Protobuf into consumers…

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \

Review comment:
       I think you'll appreciate the ArrayFromJSON and ArrayFromVector helpers here. 
   
   https://github.com/apache/arrow/blob/721aa019aa0cb3b6a15aa358a53f39e2c5c541ae/cpp/src/arrow/testing/gtest_util.h#L318-L322
   
   https://github.com/apache/arrow/blob/721aa019aa0cb3b6a15aa358a53f39e2c5c541ae/cpp/src/arrow/testing/gtest_util.h#L350-L355

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+               STATIC_LINK_LIBS
+               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+               GTest::gtest
+               GTest::gmock

Review comment:
       Are these not already in ARROW_TEST_LINK_LIBS?

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H

Review comment:
       nit, but most Arrow headers use `#pragma once` (non-standard) over the `#ifndef` pattern.

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_server.cc
##########
@@ -0,0 +1,710 @@
+// 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/flight-sql/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const pb::sql::CommandGetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.has_catalog()) {
+    table_query << " and catalog_name='" << command.catalog() << "'";
+  }
+
+  if (command.has_schema_filter_pattern()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern() << "'";
+  }
+
+  if (command.has_table_name_filter_pattern()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern() << "'";
+  }
+
+  if (!command.table_types().empty()) {
+    google::protobuf::RepeatedPtrField<std::string> types = command.table_types();
+
+    table_query << " and table_type IN (";
+    int size = types.size();
+    for (int i = 0; i < size; i++) {
+      table_query << "'" << types.at(i) << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt,
+                                      std::unique_ptr<FlightMessageReader>& reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = reinterpret_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = reinterpret_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = reinterpret_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer =
+                reinterpret_cast<StringScalar&>(*holder).value;
+            const std::string string = buffer->ToString();
+            const char* value = string.c_str();
+            sqlite3_bind_text(stmt, c + 1, value, static_cast<int>(strlen(value)),
+                              SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer =
+                reinterpret_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer() {
+  db_ = NULLPTR;
+  if (sqlite3_open(":memory:", &db_)) {
+    sqlite3_close(db_);
+    throw std::runtime_error(std::string("Can't open database: ") + sqlite3_errmsg(db_));

Review comment:
       nit: generally we don't use exceptions, complex initialization like this either happens with a combo of private constructor + public static factory method or with an Init() method on the object.

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_server.cc
##########
@@ -0,0 +1,710 @@
+// 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/flight-sql/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const pb::sql::CommandGetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.has_catalog()) {
+    table_query << " and catalog_name='" << command.catalog() << "'";
+  }
+
+  if (command.has_schema_filter_pattern()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern() << "'";
+  }
+
+  if (command.has_table_name_filter_pattern()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern() << "'";
+  }
+
+  if (!command.table_types().empty()) {
+    google::protobuf::RepeatedPtrField<std::string> types = command.table_types();
+
+    table_query << " and table_type IN (";
+    int size = types.size();
+    for (int i = 0; i < size; i++) {
+      table_query << "'" << types.at(i) << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt,
+                                      std::unique_ptr<FlightMessageReader>& reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = reinterpret_cast<DenseUnionScalar&>(*scalar).value;

Review comment:
       static_cast<const DenseUnionScalar&>?

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_server.cc
##########
@@ -0,0 +1,710 @@
+// 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/flight-sql/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const pb::sql::CommandGetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.has_catalog()) {
+    table_query << " and catalog_name='" << command.catalog() << "'";
+  }
+
+  if (command.has_schema_filter_pattern()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern() << "'";
+  }
+
+  if (command.has_table_name_filter_pattern()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern() << "'";
+  }
+
+  if (!command.table_types().empty()) {
+    google::protobuf::RepeatedPtrField<std::string> types = command.table_types();
+
+    table_query << " and table_type IN (";
+    int size = types.size();
+    for (int i = 0; i < size; i++) {
+      table_query << "'" << types.at(i) << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt,
+                                      std::unique_ptr<FlightMessageReader>& reader) {

Review comment:
       nit: just take FlightMessageReader* over a reference to a unique_ptr (in general, Arrow avoids non-const references)

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \param schema   The parameter schema from the query.
+  /// \return         Status.
+  Status GetParameterSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \param schema   The ResultSet schema from the query.
+  /// \return         Status.
+  Status GetResultSetSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding_   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.
+  /// \return Status.
+  Status Close();
+
+  /// \brief Checks if the prepared statement is closed.
+  /// \return The state of the prepared statement.
+  bool IsClosed() const;
+};
+
+/// \brief Flight client with Flight SQL semantics.
+template <class T = arrow::flight::FlightClient>
+class FlightSqlClientT {
+ public:
+  explicit FlightSqlClientT(std::unique_ptr<T>& client);
+
+  ~FlightSqlClientT();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset
+  /// \return Status.
+  Status Execute(const FlightCallOptions& options, const std::string& query,
+                 std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] rows        The quantity of rows affected by the operation.
+  /// \return Status.
+  Status ExecuteUpdate(const FlightCallOptions& options, const std::string& query,
+                       int64_t* rows) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset.
+  /// \return Status.
+  Status GetCatalogs(const FlightCallOptions& options,
+                     std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \param[out] flight_info           The FlightInfo describing where to access the
+  ///                                   dataset.
+  /// \return Status.
+  Status GetSchemas(const FlightCallOptions& options, const std::string* catalog,
+                    const std::string* schema_filter_pattern,
+                    std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \param[out] stream the returned RecordBatchReader
+  /// \return Status
+  Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream) const;

Review comment:
       These methods aren't const normally; why are they const now?

##########
File path: cpp/src/arrow/flight/flight-sql/client_impl.h
##########
@@ -0,0 +1,463 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/testing/gtest_util.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/message_lite.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T>
+FlightSqlClientT<T>::FlightSqlClientT(std::unique_ptr<T>& client) {
+  this->client = std::move(client);
+}
+
+template <class T>
+PreparedStatementT<T>::PreparedStatementT(
+    T* client_, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result_,
+    const FlightCallOptions& options_)
+    : client(client_),
+      prepared_statement_result(std::move(prepared_statement_result_)),
+      options(options_) {
+  is_closed = false;
+}
+
+template <class T>
+FlightSqlClientT<T>::~FlightSqlClientT() = default;
+
+template <class T>
+PreparedStatementT<T>::~PreparedStatementT<T>() {
+  Close();
+}
+
+inline FlightDescriptor GetFlightDescriptorForCommand(
+    const google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+template <class T>
+Status GetFlightInfoForCommand(const std::unique_ptr<T>& client,
+                               const FlightCallOptions& options,
+                               std::unique_ptr<FlightInfo>* flight_info,
+                               const google::protobuf::Message& command) {
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  return client->GetFlightInfo(options, descriptor, flight_info);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::Execute(const FlightCallOptions& options,
+                                    const std::string& query,
+                                    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::ExecuteUpdate(const FlightCallOptions& options,
+                                          const std::string& query, int64_t* rows) const {
+  pb::sql::CommandStatementUpdate command;
+  command.set_query(query);
+
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+
+  ARROW_RETURN_NOT_OK(client->DoPut(options, descriptor, NULLPTR, &writer, &reader));
+
+  std::shared_ptr<Buffer> metadata;
+
+  const Status& status = reader->ReadMetadata(&metadata);
+
+  pb::sql::DoPutUpdateResult doPutUpdateResult;
+
+  Buffer* pBuffer = metadata.get();
+
+  const std::string& string = pBuffer->ToString();
+
+  doPutUpdateResult.ParseFrom<google::protobuf::MessageLite::kParse>(string);

Review comment:
       Is Protobuf not able to parse from a string_view or pointer+length?

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       It seems odd that the test has to be separately linked to the generated Protobuf sources.

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);

Review comment:
       nit: call_options isn't a parameter here

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;

Review comment:
       I worry this can lead to dangling references; might it be better to hold a shared_ptr here? Either of the Flight client (in which case we can just promote unique_ptr<FlightClient> to shared_ptr<FlightClient> internally in the FlightSqlClient), or of the FlightSql client (in which case it needs enable_shared_from_this)

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \param schema   The parameter schema from the query.
+  /// \return         Status.
+  Status GetParameterSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \param schema   The ResultSet schema from the query.
+  /// \return         Status.
+  Status GetResultSetSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding_   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.
+  /// \return Status.
+  Status Close();
+
+  /// \brief Checks if the prepared statement is closed.
+  /// \return The state of the prepared statement.
+  bool IsClosed() const;
+};
+
+/// \brief Flight client with Flight SQL semantics.
+template <class T = arrow::flight::FlightClient>
+class FlightSqlClientT {
+ public:
+  explicit FlightSqlClientT(std::unique_ptr<T>& client);
+
+  ~FlightSqlClientT();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset
+  /// \return Status.
+  Status Execute(const FlightCallOptions& options, const std::string& query,
+                 std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] rows        The quantity of rows affected by the operation.
+  /// \return Status.
+  Status ExecuteUpdate(const FlightCallOptions& options, const std::string& query,
+                       int64_t* rows) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset.
+  /// \return Status.
+  Status GetCatalogs(const FlightCallOptions& options,
+                     std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \param[out] flight_info           The FlightInfo describing where to access the
+  ///                                   dataset.
+  /// \return Status.
+  Status GetSchemas(const FlightCallOptions& options, const std::string* catalog,
+                    const std::string* schema_filter_pattern,
+                    std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \param[out] stream the returned RecordBatchReader
+  /// \return Status
+  Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream) const;
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \param[out] flight_info             The FlightInfo describing where to access the
+  ///                                     dataset.
+  /// \return Status.
+  Status GetTables(const FlightCallOptions& options, const std::string* catalog,

Review comment:
       These should be `const std::string&`.

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.cpp
##########
@@ -0,0 +1,104 @@
+// 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/flight-sql/example/sqlite_tables_schema_batch_reader.h"
+
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/ipc/writer.h>
+#include <arrow/record_batch.h>
+#include <sqlite3.h>
+
+#include <sstream>
+
+#include "arrow/flight/flight-sql/example/sqlite_server.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<Schema> SqliteTablesWithSchemaBatchReader::schema() const {
+  return SqlSchema::GetTablesSchemaWithIncludedSchema();
+}
+
+Status SqliteTablesWithSchemaBatchReader::ReadNext(std::shared_ptr<RecordBatch>* batch) {
+  std::stringstream schema_query;
+
+  schema_query
+      << "SELECT table_name, name, type, [notnull] FROM pragma_table_info(table_name)"
+      << "JOIN(" << main_query_ << ") order by table_name";
+
+  std::shared_ptr<example::SqliteStatement> schema_statement;
+  ARROW_RETURN_NOT_OK(
+      example::SqliteStatement::Create(db_, schema_query.str(), &schema_statement));
+
+  std::shared_ptr<RecordBatch> first_batch;
+
+  ARROW_RETURN_NOT_OK(reader_->ReadNext(&first_batch));
+
+  if (!first_batch) {
+    *batch = NULLPTR;
+    return Status::OK();
+  }
+
+  const std::shared_ptr<Array> table_name_array =
+      first_batch->GetColumnByName("table_name");
+
+  BinaryBuilder schema_builder;
+
+  auto* string_array = reinterpret_cast<StringArray*>(table_name_array.get());
+
+  std::vector<std::shared_ptr<Field>> column_fields;
+  for (int i = 0; i < table_name_array->length(); i++) {
+    const std::string& table_name = string_array->GetString(i);
+
+    while (sqlite3_step(schema_statement->GetSqlite3Stmt()) == SQLITE_ROW) {
+      std::string sqlite_table_name = std::string(reinterpret_cast<const char*>(
+          sqlite3_column_text(schema_statement->GetSqlite3Stmt(), 0)));
+      if (sqlite_table_name == table_name) {
+        const char* column_name = reinterpret_cast<const char*>(
+            sqlite3_column_text(schema_statement->GetSqlite3Stmt(), 1));
+        const char* column_type = reinterpret_cast<const char*>(
+            sqlite3_column_text(schema_statement->GetSqlite3Stmt(), 2));
+        int nullable = sqlite3_column_int(schema_statement->GetSqlite3Stmt(), 3);
+
+        column_fields.push_back(
+            arrow::field(column_name, GetArrowType(column_type), nullable == 0, NULL));
+      }
+    }
+    const arrow::Result<std::shared_ptr<Buffer>>& value =
+        ipc::SerializeSchema(*arrow::schema(column_fields));

Review comment:
       ARROW_ASSIGN_OR_RAISE is probably what you want here

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,404 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/server.h>
+#include <google/protobuf/any.pb.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlServerBase : public FlightServerBase {
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType FLIGHT_SQL_CREATE_PREPARED_STATEMENT =
+      ActionType{.type = "CreatePreparedStatement",

Review comment:
       Huh, do all our compilers support this? Would be nice if CI pans out.

##########
File path: cpp/src/arrow/flight/flight-sql/test_app_cli.cc
##########
@@ -0,0 +1,200 @@
+// 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/array/builder_binary.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/io/memory.h>
+#include <arrow/pretty_print.h>
+#include <arrow/status.h>
+#include <arrow/table.h>
+#include <gflags/gflags.h>
+
+#include <boost/algorithm/string.hpp>
+#include <iostream>
+#include <memory>
+
+using arrow::Result;
+using arrow::Schema;
+using arrow::Status;
+using arrow::flight::ClientAuthHandler;
+using arrow::flight::FlightCallOptions;
+using arrow::flight::FlightClient;
+using arrow::flight::FlightDescriptor;
+using arrow::flight::FlightEndpoint;
+using arrow::flight::FlightInfo;
+using arrow::flight::FlightStreamChunk;
+using arrow::flight::FlightStreamReader;
+using arrow::flight::Location;
+using arrow::flight::Ticket;
+using arrow::flight::sql::FlightSqlClient;
+
+DEFINE_string(host, "localhost", "Host to connect to");
+DEFINE_int32(port, 32010, "Port to connect to");
+DEFINE_string(username, "", "Username");
+DEFINE_string(password, "", "Password");
+
+DEFINE_string(command, "", "Method to run");
+DEFINE_string(query, "", "Query");
+DEFINE_string(catalog, "", "Catalog");
+DEFINE_string(schema, "", "Schema");
+DEFINE_string(table, "", "Table");
+
+Status PrintResultsForEndpoint(const FlightSqlClient& client,
+                               const FlightCallOptions& call_options,
+                               const FlightEndpoint& endpoint) {
+  std::unique_ptr<FlightStreamReader> stream;
+  ARROW_RETURN_NOT_OK(client.DoGet(call_options, endpoint.ticket, &stream));
+
+  const arrow::Result<std::shared_ptr<Schema>>& schema = stream->GetSchema();
+  ARROW_RETURN_NOT_OK(schema);
+
+  std::cout << "Schema:" << std::endl;
+  std::cout << schema->get()->ToString() << std::endl << std::endl;
+
+  std::cout << "Results:" << std::endl;
+
+  FlightStreamChunk chunk;
+  int64_t num_rows = 0;
+
+  while (true) {
+    ARROW_RETURN_NOT_OK(stream->Next(&chunk));
+    if (!(chunk.data != nullptr)) {
+      break;
+    }
+    std::cout << chunk.data->ToString() << std::endl;
+    num_rows += chunk.data->num_rows();
+  }
+
+  std::cout << "Total: " << num_rows << std::endl;
+
+  return Status::OK();
+}
+
+Status PrintResults(FlightSqlClient& client, const FlightCallOptions& call_options,
+                    const std::unique_ptr<FlightInfo>& info) {
+  const std::vector<FlightEndpoint>& endpoints = info->endpoints();
+
+  for (size_t i = 0; i < endpoints.size(); i++) {
+    std::cout << "Results from endpoint " << i + 1 << " of " << endpoints.size()
+              << std::endl;
+    ARROW_RETURN_NOT_OK(PrintResultsForEndpoint(client, call_options, endpoints[i]));
+  }
+
+  return Status::OK();
+}
+
+Status RunMain() {
+  std::unique_ptr<FlightClient> client;
+  Location location;
+  ARROW_RETURN_NOT_OK(Location::ForGrpcTcp(fLS::FLAGS_host, fLI::FLAGS_port, &location));
+  ARROW_RETURN_NOT_OK(FlightClient::Connect(location, &client));
+
+  FlightCallOptions call_options;
+
+  if (!fLS::FLAGS_username.empty() || !fLS::FLAGS_password.empty()) {
+    Result<std::pair<std::string, std::string>> bearer_result =
+        client->AuthenticateBasicToken({}, fLS::FLAGS_username, fLS::FLAGS_password);
+    ARROW_RETURN_NOT_OK(bearer_result);
+
+    call_options.headers.push_back(bearer_result.ValueOrDie());
+  }
+
+  FlightSqlClient sqlClient(client);
+
+  if (fLS::FLAGS_command == "ExecuteUpdate") {
+    int64_t rows;
+    ARROW_RETURN_NOT_OK(sqlClient.ExecuteUpdate(call_options, fLS::FLAGS_query, &rows));
+
+    std::cout << "Result: " << rows << std::endl;
+
+    return Status::OK();
+  }
+
+  std::unique_ptr<FlightInfo> info;
+
+  if (fLS::FLAGS_command == "Execute") {

Review comment:
       Where do these fLS/fLI namespaces come from?

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_server.cc
##########
@@ -0,0 +1,710 @@
+// 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/flight-sql/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const pb::sql::CommandGetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.has_catalog()) {
+    table_query << " and catalog_name='" << command.catalog() << "'";
+  }
+
+  if (command.has_schema_filter_pattern()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern() << "'";
+  }
+
+  if (command.has_table_name_filter_pattern()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern() << "'";
+  }
+
+  if (!command.table_types().empty()) {
+    google::protobuf::RepeatedPtrField<std::string> types = command.table_types();
+
+    table_query << " and table_type IN (";
+    int size = types.size();
+    for (int i = 0; i < size; i++) {
+      table_query << "'" << types.at(i) << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt,
+                                      std::unique_ptr<FlightMessageReader>& reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = reinterpret_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = reinterpret_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = reinterpret_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer =
+                reinterpret_cast<StringScalar&>(*holder).value;
+            const std::string string = buffer->ToString();
+            const char* value = string.c_str();
+            sqlite3_bind_text(stmt, c + 1, value, static_cast<int>(strlen(value)),
+                              SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer =
+                reinterpret_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer() {
+  db_ = NULLPTR;
+  if (sqlite3_open(":memory:", &db_)) {
+    sqlite3_close(db_);
+    throw std::runtime_error(std::string("Can't open database: ") + sqlite3_errmsg(db_));
+  }
+
+  ExecuteSql(R"(
+CREATE TABLE foreignTable (
+  id INTEGER PRIMARY KEY AUTOINCREMENT,
+  foreignName varchar(100),
+  value int);
+
+CREATE TABLE intTable (
+  id INTEGER PRIMARY KEY AUTOINCREMENT,
+  keyName varchar(100),
+  value int,
+  foreignId int references foreignTable(id));
+
+INSERT INTO foreignTable (foreignName, value) VALUES ('keyOne', 1);
+INSERT INTO foreignTable (foreignName, value) VALUES ('keyTwo', 0);
+INSERT INTO foreignTable (foreignName, value) VALUES ('keyThree', -1);
+INSERT INTO intTable (keyName, value, foreignId) VALUES ('one', 1, 1);
+INSERT INTO intTable (keyName, value, foreignId) VALUES ('zero', 0, 1);
+INSERT INTO intTable (keyName, value, foreignId) VALUES ('negative one', -1, 1);
+  )");
+}
+
+SQLiteFlightSqlServer::~SQLiteFlightSqlServer() { sqlite3_close(db_); }
+
+void SQLiteFlightSqlServer::ExecuteSql(const std::string& sql) {
+  char* zErrMsg = NULLPTR;
+  int rc = sqlite3_exec(db_, sql.c_str(), NULLPTR, NULLPTR, &zErrMsg);
+  if (rc != SQLITE_OK) {
+    fprintf(stderr, "SQL error: %s\n", zErrMsg);
+    sqlite3_free(zErrMsg);
+  }
+}
+
+Status DoGetSQLiteQuery(sqlite3* db, const std::string& query,
+                        const std::shared_ptr<Schema>& schema,
+                        std::unique_ptr<FlightDataStream>* result) {
+  std::shared_ptr<SqliteStatement> statement;
+  ARROW_RETURN_NOT_OK(SqliteStatement::Create(db, query, &statement));
+
+  std::shared_ptr<SqliteStatementBatchReader> reader;
+  ARROW_RETURN_NOT_OK(SqliteStatementBatchReader::Create(statement, schema, &reader));
+
+  *result = std::unique_ptr<FlightDataStream>(new RecordBatchStream(reader));
+
+  return Status::OK();
+}
+
+Status GetFlightInfoForCommand(const FlightDescriptor& descriptor,
+                               std::unique_ptr<FlightInfo>* info,
+                               const google::protobuf::Message& command,
+                               const std::shared_ptr<Schema>& schema) {
+  google::protobuf::Any ticketParsed;

Review comment:
       nit: `ticket_parsed`

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \param schema   The parameter schema from the query.
+  /// \return         Status.
+  Status GetParameterSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \param schema   The ResultSet schema from the query.
+  /// \return         Status.
+  Status GetResultSetSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding_   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.
+  /// \return Status.
+  Status Close();
+
+  /// \brief Checks if the prepared statement is closed.
+  /// \return The state of the prepared statement.
+  bool IsClosed() const;
+};
+
+/// \brief Flight client with Flight SQL semantics.
+template <class T = arrow::flight::FlightClient>
+class FlightSqlClientT {
+ public:
+  explicit FlightSqlClientT(std::unique_ptr<T>& client);
+
+  ~FlightSqlClientT();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset
+  /// \return Status.
+  Status Execute(const FlightCallOptions& options, const std::string& query,
+                 std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] rows        The quantity of rows affected by the operation.
+  /// \return Status.
+  Status ExecuteUpdate(const FlightCallOptions& options, const std::string& query,
+                       int64_t* rows) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset.
+  /// \return Status.
+  Status GetCatalogs(const FlightCallOptions& options,
+                     std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \param[out] flight_info           The FlightInfo describing where to access the
+  ///                                   dataset.
+  /// \return Status.
+  Status GetSchemas(const FlightCallOptions& options, const std::string* catalog,
+                    const std::string* schema_filter_pattern,
+                    std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \param[out] stream the returned RecordBatchReader
+  /// \return Status
+  Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream) const;
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \param[out] flight_info             The FlightInfo describing where to access the
+  ///                                     dataset.
+  /// \return Status.
+  Status GetTables(const FlightCallOptions& options, const std::string* catalog,

Review comment:
       Ah, these are for optional arguments. Is there any downside to treating empty string as not present? (I suppose our Protobuf differentiates between the two now.)

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       (The analogous files are omitted for Flight since they get #included into another file, but that doesn't apply here.)

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,572 @@
+// 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/api.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/types.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+using internal::FlightSqlClientT;
+
+class FlightClientMock {
+ public:
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto* client_mock = new FlightClientMock();
+  std::unique_ptr<FlightClientMock> client_mock_ptr(client_mock);
+  FlightSqlClientT<FlightClientMock> sqlClient(client_mock_ptr);
+  FlightCallOptions call_options;
+
+  pb::sql::CommandGetCatalogs command;
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  std::unique_ptr<FlightInfo> flight_info;
+  EXPECT_CALL(*client_mock, GetFlightInfo(Ref(call_options), descriptor, &flight_info));
+
+  (void)sqlClient.GetCatalogs(call_options, &flight_info);
+}
+
+TEST(TestFlightSqlClient, TestGetSchemas) {
+  auto* client_mock = new FlightClientMock();
+  std::unique_ptr<FlightClientMock> client_mock_ptr(client_mock);
+  FlightSqlClientT<FlightClientMock> sqlClient(client_mock_ptr);
+  FlightCallOptions call_options;
+
+  std::string schema_filter_pattern = "schema_filter_pattern";
+  std::string catalog = "catalog";
+
+  pb::sql::CommandGetSchemas command;
+  command.set_catalog(catalog);
+  command.set_schema_filter_pattern(schema_filter_pattern);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  std::unique_ptr<FlightInfo> flight_info;
+  EXPECT_CALL(*client_mock, GetFlightInfo(Ref(call_options), descriptor, &flight_info));
+
+  (void)sqlClient.GetSchemas(call_options, &catalog, &schema_filter_pattern,

Review comment:
       (Also I think we have ARROW_UNUSED for this)

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.cpp
##########
@@ -0,0 +1,104 @@
+// 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/flight-sql/example/sqlite_tables_schema_batch_reader.h"
+
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/ipc/writer.h>
+#include <arrow/record_batch.h>
+#include <sqlite3.h>
+
+#include <sstream>
+
+#include "arrow/flight/flight-sql/example/sqlite_server.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<Schema> SqliteTablesWithSchemaBatchReader::schema() const {
+  return SqlSchema::GetTablesSchemaWithIncludedSchema();
+}
+
+Status SqliteTablesWithSchemaBatchReader::ReadNext(std::shared_ptr<RecordBatch>* batch) {
+  std::stringstream schema_query;
+
+  schema_query
+      << "SELECT table_name, name, type, [notnull] FROM pragma_table_info(table_name)"
+      << "JOIN(" << main_query_ << ") order by table_name";
+
+  std::shared_ptr<example::SqliteStatement> schema_statement;
+  ARROW_RETURN_NOT_OK(
+      example::SqliteStatement::Create(db_, schema_query.str(), &schema_statement));
+
+  std::shared_ptr<RecordBatch> first_batch;
+
+  ARROW_RETURN_NOT_OK(reader_->ReadNext(&first_batch));
+
+  if (!first_batch) {
+    *batch = NULLPTR;
+    return Status::OK();
+  }
+
+  const std::shared_ptr<Array> table_name_array =
+      first_batch->GetColumnByName("table_name");
+
+  BinaryBuilder schema_builder;
+
+  auto* string_array = reinterpret_cast<StringArray*>(table_name_array.get());
+
+  std::vector<std::shared_ptr<Field>> column_fields;
+  for (int i = 0; i < table_name_array->length(); i++) {
+    const std::string& table_name = string_array->GetString(i);
+
+    while (sqlite3_step(schema_statement->GetSqlite3Stmt()) == SQLITE_ROW) {
+      std::string sqlite_table_name = std::string(reinterpret_cast<const char*>(
+          sqlite3_column_text(schema_statement->GetSqlite3Stmt(), 0)));
+      if (sqlite_table_name == table_name) {
+        const char* column_name = reinterpret_cast<const char*>(
+            sqlite3_column_text(schema_statement->GetSqlite3Stmt(), 1));
+        const char* column_type = reinterpret_cast<const char*>(
+            sqlite3_column_text(schema_statement->GetSqlite3Stmt(), 2));
+        int nullable = sqlite3_column_int(schema_statement->GetSqlite3Stmt(), 3);
+
+        column_fields.push_back(
+            arrow::field(column_name, GetArrowType(column_type), nullable == 0, NULL));
+      }
+    }
+    const arrow::Result<std::shared_ptr<Buffer>>& value =
+        ipc::SerializeSchema(*arrow::schema(column_fields));
+    column_fields.clear();
+    ARROW_RETURN_NOT_OK(
+        schema_builder.Append(value.ValueOrDie()->data(), value.ValueOrDie()->size()));
+  }
+
+  std::shared_ptr<Array> schema_array;
+  ARROW_RETURN_NOT_OK(schema_builder.Finish(&schema_array));
+
+  auto result = first_batch->AddColumn(4, "table_schema", schema_array);
+
+  ARROW_ASSIGN_OR_RAISE(*batch, result);

Review comment:
       Also you can do something like `ARROW_ASSIGN_OR_RAISE(*batch, first_batch->AddColumn(...));`

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,404 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/server.h>
+#include <google/protobuf/any.pb.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlServerBase : public FlightServerBase {
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType FLIGHT_SQL_CREATE_PREPARED_STATEMENT =
+      ActionType{.type = "CreatePreparedStatement",
+                 .description =
+                     "Creates a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionCreatePreparedStatementRequest\n"
+                     "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType FLIGHT_SQL_CLOSE_PREPARED_STATEMENT =
+      ActionType{.type = "ClosePreparedStatement",
+                 .description =
+                     "Closes a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionClosePreparedStatementRequest\n"
+                     "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] command      The CommandStatementQuery object containing the SQL
+  ///                         statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const pb::sql::CommandStatementQuery& command,

Review comment:
       I guess I'm +0 on this for now.

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);

Review comment:
       And ditto below. (Sorry for the churn.)

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \

Review comment:
       There's a TableFromJSON as well.

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

Review comment:
       Could we instead poll in a loop so that we don't always have to wait a full second?

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_server.cc
##########
@@ -0,0 +1,710 @@
+// 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/flight-sql/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const pb::sql::CommandGetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.has_catalog()) {
+    table_query << " and catalog_name='" << command.catalog() << "'";
+  }
+
+  if (command.has_schema_filter_pattern()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern() << "'";
+  }
+
+  if (command.has_table_name_filter_pattern()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern() << "'";
+  }
+
+  if (!command.table_types().empty()) {
+    google::protobuf::RepeatedPtrField<std::string> types = command.table_types();
+
+    table_query << " and table_type IN (";
+    int size = types.size();
+    for (int i = 0; i < size; i++) {
+      table_query << "'" << types.at(i) << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt,
+                                      std::unique_ptr<FlightMessageReader>& reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = reinterpret_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = reinterpret_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = reinterpret_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer =
+                reinterpret_cast<StringScalar&>(*holder).value;
+            const std::string string = buffer->ToString();
+            const char* value = string.c_str();
+            sqlite3_bind_text(stmt, c + 1, value, static_cast<int>(strlen(value)),
+                              SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer =
+                reinterpret_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer() {
+  db_ = NULLPTR;
+  if (sqlite3_open(":memory:", &db_)) {
+    sqlite3_close(db_);
+    throw std::runtime_error(std::string("Can't open database: ") + sqlite3_errmsg(db_));
+  }
+
+  ExecuteSql(R"(
+CREATE TABLE foreignTable (
+  id INTEGER PRIMARY KEY AUTOINCREMENT,
+  foreignName varchar(100),
+  value int);
+
+CREATE TABLE intTable (
+  id INTEGER PRIMARY KEY AUTOINCREMENT,
+  keyName varchar(100),
+  value int,
+  foreignId int references foreignTable(id));
+
+INSERT INTO foreignTable (foreignName, value) VALUES ('keyOne', 1);
+INSERT INTO foreignTable (foreignName, value) VALUES ('keyTwo', 0);
+INSERT INTO foreignTable (foreignName, value) VALUES ('keyThree', -1);
+INSERT INTO intTable (keyName, value, foreignId) VALUES ('one', 1, 1);
+INSERT INTO intTable (keyName, value, foreignId) VALUES ('zero', 0, 1);
+INSERT INTO intTable (keyName, value, foreignId) VALUES ('negative one', -1, 1);
+  )");
+}
+
+SQLiteFlightSqlServer::~SQLiteFlightSqlServer() { sqlite3_close(db_); }
+
+void SQLiteFlightSqlServer::ExecuteSql(const std::string& sql) {
+  char* zErrMsg = NULLPTR;
+  int rc = sqlite3_exec(db_, sql.c_str(), NULLPTR, NULLPTR, &zErrMsg);
+  if (rc != SQLITE_OK) {
+    fprintf(stderr, "SQL error: %s\n", zErrMsg);
+    sqlite3_free(zErrMsg);
+  }

Review comment:
       A couple things:
   - `z_err_msg` or just `err_msg` to fit the naming scheme?
   - NULLPTR is only required in header files, for what it's worth.
   - Why not return the error as a Status?

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client = new FlightSqlClient(client);
+  }
+
+  void TearDown() override {
+    server->Stop();
+
+    free(server);
+    free(sql_client);

Review comment:
       delete?

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_server.cc
##########
@@ -0,0 +1,710 @@
+// 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/flight-sql/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const pb::sql::CommandGetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.has_catalog()) {
+    table_query << " and catalog_name='" << command.catalog() << "'";
+  }
+
+  if (command.has_schema_filter_pattern()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern() << "'";
+  }
+
+  if (command.has_table_name_filter_pattern()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern() << "'";
+  }
+
+  if (!command.table_types().empty()) {
+    google::protobuf::RepeatedPtrField<std::string> types = command.table_types();
+
+    table_query << " and table_type IN (";
+    int size = types.size();
+    for (int i = 0; i < size; i++) {
+      table_query << "'" << types.at(i) << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt,
+                                      std::unique_ptr<FlightMessageReader>& reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = reinterpret_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = reinterpret_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = reinterpret_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer =
+                reinterpret_cast<StringScalar&>(*holder).value;
+            const std::string string = buffer->ToString();
+            const char* value = string.c_str();
+            sqlite3_bind_text(stmt, c + 1, value, static_cast<int>(strlen(value)),

Review comment:
       You should be able to use buffer->data() and buffer->size() (with some casting) instead of allocating a new string.

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_statement.h
##########
@@ -0,0 +1,74 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include "arrow/api.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+class SqliteStatement {
+ public:
+  /// \brief Creates a SQLite3 statement.
+  /// \param[in] db        SQLite3 database instance.
+  /// \param[in] sql       SQL statement.
+  /// \param[out] result   The resulting SqliteStatement.
+  /// \return              Status.
+  static Status Create(sqlite3* db, const std::string& sql,
+                       std::shared_ptr<SqliteStatement>* result);

Review comment:
       This, too, might be better as `Result<std::shared_ptr<SqliteStatement>>` (and ditto below)

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.cpp
##########
@@ -0,0 +1,104 @@
+// Licensed to the Apache Software Foundation (ASF) under one

Review comment:
       nit: this file has extension cpp, should have extension cc

##########
File path: cpp/src/arrow/flight/flight-sql/test_app_cli.cc
##########
@@ -0,0 +1,200 @@
+// 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/array/builder_binary.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/io/memory.h>
+#include <arrow/pretty_print.h>
+#include <arrow/status.h>
+#include <arrow/table.h>
+#include <gflags/gflags.h>
+
+#include <boost/algorithm/string.hpp>
+#include <iostream>
+#include <memory>
+
+using arrow::Result;
+using arrow::Schema;
+using arrow::Status;
+using arrow::flight::ClientAuthHandler;
+using arrow::flight::FlightCallOptions;
+using arrow::flight::FlightClient;
+using arrow::flight::FlightDescriptor;
+using arrow::flight::FlightEndpoint;
+using arrow::flight::FlightInfo;
+using arrow::flight::FlightStreamChunk;
+using arrow::flight::FlightStreamReader;
+using arrow::flight::Location;
+using arrow::flight::Ticket;
+using arrow::flight::sql::FlightSqlClient;
+
+DEFINE_string(host, "localhost", "Host to connect to");
+DEFINE_int32(port, 32010, "Port to connect to");
+DEFINE_string(username, "", "Username");
+DEFINE_string(password, "", "Password");
+
+DEFINE_string(command, "", "Method to run");
+DEFINE_string(query, "", "Query");
+DEFINE_string(catalog, "", "Catalog");
+DEFINE_string(schema, "", "Schema");
+DEFINE_string(table, "", "Table");
+
+Status PrintResultsForEndpoint(const FlightSqlClient& client,
+                               const FlightCallOptions& call_options,
+                               const FlightEndpoint& endpoint) {
+  std::unique_ptr<FlightStreamReader> stream;
+  ARROW_RETURN_NOT_OK(client.DoGet(call_options, endpoint.ticket, &stream));
+
+  const arrow::Result<std::shared_ptr<Schema>>& schema = stream->GetSchema();
+  ARROW_RETURN_NOT_OK(schema);
+
+  std::cout << "Schema:" << std::endl;
+  std::cout << schema->get()->ToString() << std::endl << std::endl;
+
+  std::cout << "Results:" << std::endl;
+
+  FlightStreamChunk chunk;
+  int64_t num_rows = 0;
+
+  while (true) {
+    ARROW_RETURN_NOT_OK(stream->Next(&chunk));
+    if (!(chunk.data != nullptr)) {
+      break;
+    }
+    std::cout << chunk.data->ToString() << std::endl;
+    num_rows += chunk.data->num_rows();
+  }
+
+  std::cout << "Total: " << num_rows << std::endl;
+
+  return Status::OK();
+}
+
+Status PrintResults(FlightSqlClient& client, const FlightCallOptions& call_options,
+                    const std::unique_ptr<FlightInfo>& info) {
+  const std::vector<FlightEndpoint>& endpoints = info->endpoints();
+
+  for (size_t i = 0; i < endpoints.size(); i++) {
+    std::cout << "Results from endpoint " << i + 1 << " of " << endpoints.size()
+              << std::endl;
+    ARROW_RETURN_NOT_OK(PrintResultsForEndpoint(client, call_options, endpoints[i]));
+  }
+
+  return Status::OK();
+}
+
+Status RunMain() {
+  std::unique_ptr<FlightClient> client;
+  Location location;
+  ARROW_RETURN_NOT_OK(Location::ForGrpcTcp(fLS::FLAGS_host, fLI::FLAGS_port, &location));
+  ARROW_RETURN_NOT_OK(FlightClient::Connect(location, &client));
+
+  FlightCallOptions call_options;
+
+  if (!fLS::FLAGS_username.empty() || !fLS::FLAGS_password.empty()) {
+    Result<std::pair<std::string, std::string>> bearer_result =
+        client->AuthenticateBasicToken({}, fLS::FLAGS_username, fLS::FLAGS_password);
+    ARROW_RETURN_NOT_OK(bearer_result);
+
+    call_options.headers.push_back(bearer_result.ValueOrDie());
+  }
+
+  FlightSqlClient sqlClient(client);
+
+  if (fLS::FLAGS_command == "ExecuteUpdate") {
+    int64_t rows;
+    ARROW_RETURN_NOT_OK(sqlClient.ExecuteUpdate(call_options, fLS::FLAGS_query, &rows));
+
+    std::cout << "Result: " << rows << std::endl;
+
+    return Status::OK();
+  }
+
+  std::unique_ptr<FlightInfo> info;
+
+  if (fLS::FLAGS_command == "Execute") {

Review comment:
       I guess it comes from gflags - but FLAGS_command by itself should be usable?

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_tables_schema_batch_reader.h
##########
@@ -0,0 +1,60 @@
+// 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.
+
+#ifndef ARROW_SQLITE_TABLES_SCHEMA_BATCH_READER_H
+#define ARROW_SQLITE_TABLES_SCHEMA_BATCH_READER_H
+
+#include <arrow/record_batch.h>
+#include <sqlite3.h>
+
+#include <sstream>
+#include <utility>
+
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+class SqliteTablesWithSchemaBatchReader : public RecordBatchReader {
+ private:
+  std::shared_ptr<example::SqliteStatementBatchReader> reader_;
+  std::string main_query_;
+  sqlite3* db_;
+
+ public:
+  /// Constructor for SqliteTablesWithSchemaBatchReader class
+  /// \param reader an shared_ptr from a SqliteStatementBatchReader.
+  /// \param db_    a pointer to the sqlite3 db.
+  SqliteTablesWithSchemaBatchReader(
+      std::shared_ptr<example::SqliteStatementBatchReader> reader,
+      std::string& main_query, sqlite3* db)

Review comment:
       nit: const std::string&

##########
File path: cpp/src/arrow/flight/flight-sql/client_impl.h
##########
@@ -0,0 +1,463 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/testing/gtest_util.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/message_lite.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T>
+FlightSqlClientT<T>::FlightSqlClientT(std::unique_ptr<T>& client) {
+  this->client = std::move(client);
+}
+
+template <class T>
+PreparedStatementT<T>::PreparedStatementT(
+    T* client_, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result_,
+    const FlightCallOptions& options_)
+    : client(client_),
+      prepared_statement_result(std::move(prepared_statement_result_)),
+      options(options_) {
+  is_closed = false;
+}
+
+template <class T>
+FlightSqlClientT<T>::~FlightSqlClientT() = default;
+
+template <class T>
+PreparedStatementT<T>::~PreparedStatementT<T>() {
+  Close();
+}
+
+inline FlightDescriptor GetFlightDescriptorForCommand(
+    const google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+template <class T>
+Status GetFlightInfoForCommand(const std::unique_ptr<T>& client,
+                               const FlightCallOptions& options,
+                               std::unique_ptr<FlightInfo>* flight_info,
+                               const google::protobuf::Message& command) {
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  return client->GetFlightInfo(options, descriptor, flight_info);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::Execute(const FlightCallOptions& options,
+                                    const std::string& query,
+                                    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::ExecuteUpdate(const FlightCallOptions& options,
+                                          const std::string& query, int64_t* rows) const {
+  pb::sql::CommandStatementUpdate command;
+  command.set_query(query);
+
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+
+  ARROW_RETURN_NOT_OK(client->DoPut(options, descriptor, NULLPTR, &writer, &reader));
+
+  std::shared_ptr<Buffer> metadata;
+
+  const Status& status = reader->ReadMetadata(&metadata);
+
+  pb::sql::DoPutUpdateResult doPutUpdateResult;
+
+  Buffer* pBuffer = metadata.get();
+
+  const std::string& string = pBuffer->ToString();
+
+  doPutUpdateResult.ParseFrom<google::protobuf::MessageLite::kParse>(string);

Review comment:
       Also IIRC Protobuf can throw exceptions in parsing/returns a boolean success flag that we should handle

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       Or another way, if you want to preserve the GMock usage below, would be to have pImpls/abstract base classes in this header, then a `client_internal.h` that can be included from the .cc files to implement the pImpl/abstract base class and be used in the tests.

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_statement.h
##########
@@ -0,0 +1,74 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include "arrow/api.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+class SqliteStatement {
+ public:
+  /// \brief Creates a SQLite3 statement.
+  /// \param[in] db        SQLite3 database instance.
+  /// \param[in] sql       SQL statement.
+  /// \param[out] result   The resulting SqliteStatement.
+  /// \return              Status.
+  static Status Create(sqlite3* db, const std::string& sql,
+                       std::shared_ptr<SqliteStatement>* result);
+
+  ~SqliteStatement();
+
+  /// \brief Creates an Arrow Schema based on the results of this statement.
+  /// \param[out] schema   The resulting Schema.
+  /// \return              Status.
+  Status GetSchema(std::shared_ptr<Schema>* schema) const;
+
+  /// \brief Steps on underlying sqlite3_stmt.
+  /// \param[out] rc   The resulting return code from SQLite.
+  /// \return          Status.
+  Status Step(int* rc);
+
+  /// \brief Reset the state of the sqlite3_stmt.
+  /// \param[out] rc   The resulting return code from SQLite.
+  /// \return          Status.
+  Status Reset(int* rc);
+
+  /// \brief Returns the underlying sqlite3_stmt.
+  sqlite3_stmt* GetSqlite3Stmt();

Review comment:
       `sqlite3_stmt* sqlite_statement() const;`?

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       Shouldn't this go in ARROW_FLIGHT_SQL_SRCS above?

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       It might better to extract a FlightClientInterface in flight/client.h.

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       (Also, if we do stick with this pattern, `FooImpl<T>` is more consistent with the rest of the codebase than `FooT<T>`)

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

Review comment:
       Though - what's stopping us from just starting the server in process?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735810150



##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,404 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/server.h>
+#include <google/protobuf/any.pb.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlServerBase : public FlightServerBase {
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType FLIGHT_SQL_CREATE_PREPARED_STATEMENT =
+      ActionType{.type = "CreatePreparedStatement",
+                 .description =
+                     "Creates a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionCreatePreparedStatementRequest\n"
+                     "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType FLIGHT_SQL_CLOSE_PREPARED_STATEMENT =
+      ActionType{.type = "ClosePreparedStatement",
+                 .description =
+                     "Closes a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionClosePreparedStatementRequest\n"
+                     "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] command      The CommandStatementQuery object containing the SQL
+  ///                         statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const pb::sql::CommandStatementQuery& command,

Review comment:
       @lidavidm , I think we could wrap by using simple structs, like:
   
   ```c++
   using CommandStatementQuery = struct CommandStatementQuery {
     std::string query;
   };
   ```
   
   And construct them right before delegating to the specialized methods like `GetFlightInfoStatement`. What do you think?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735806121



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       In particular, as it stands it looks like we have to compile the generated sources into the test executable - so what does that mean for future library users? Will they have to generate and compile the sources into their own executables too? (It seems so, given the example CLI and server.) I don't think we can ship something like that - so we need to figure out the root issue. I'll try to take a look at this today as well.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r736763164



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,107 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
+                                                  ${GFLAGS_LIBRARIES})
+
+add_arrow_test(flight_sql_test
+        SOURCES
+        client_test.cc
+        server_test.cc
+        "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+        STATIC_LINK_LIBS
+        ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+        LABELS
+        "arrow_flight_sql")
+
+# Build test server for unit tests
+if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
+  find_package(SQLite3)

Review comment:
       Most of our CMake files don't require anything that new, so we might want to provide `cmake_modules/FindSqlite3Alt.cmake` or similar. (At the very least we need to declare that dependency here.)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r753379103



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;

Review comment:
       Only for documentation purposes.. This does not change any behaviour




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r752431808



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name, then schema_name.
+ */
+message CommandGetSchemas {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, the pattern will not be used to narrow the search.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+}
+
+/*
+ * Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  table_type: utf8 not null,
+ *  [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema,
+ *                                           it is serialized as an IPC message.)
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, then table_type, followed by table_schema if requested.
+ */
+message CommandGetTables {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, all schemas matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+
+  /*
+   * Specifies a filter pattern for tables to search for.
+   * When no table_name_filter_pattern is provided, all tables matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string table_name_filter_pattern = 3;
+
+  // Specifies a filter of table types which must match.

Review comment:
       It is backend-specific, and be retrieved with CommandGetTableTypes.

##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null

Review comment:
       Similar to catalogs, it depends on vendor/implementation. It is usually a namespace within the database or the database itself




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r763247880



##########
File path: cpp/src/arrow/flight/sql/example/sqlite_sql_info.cc
##########
@@ -0,0 +1,223 @@
+// 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/example/sqlite_sql_info.h"
+
+#include "arrow/flight/sql/types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+/// \brief Gets the mapping from SQL info ids to SqlInfoResult instances.
+/// \return the cache.
+SqlInfoResultMap GetSqlInfoResultMap() {
+  return {
+      {SqlInfoOptions::SqlInfo::FLIGHT_SQL_SERVER_NAME,
+       SqlInfoResult(std::string("db_name"))},
+      {SqlInfoOptions::SqlInfo::FLIGHT_SQL_SERVER_VERSION,
+       SqlInfoResult(std::string("sqlite 3"))},
+      {SqlInfoOptions::SqlInfo::FLIGHT_SQL_SERVER_ARROW_VERSION,
+       SqlInfoResult(std::string("7.0.0-SNAPSHOT" /* Only an example */))},
+      {SqlInfoOptions::SqlInfo::FLIGHT_SQL_SERVER_READ_ONLY, SqlInfoResult(false)},
+      {SqlInfoOptions::SqlInfo::SQL_DDL_CATALOG,
+       SqlInfoResult(false /* SQLite 3 does not support catalogs */)},
+      {SqlInfoOptions::SqlInfo::SQL_DDL_SCHEMA,
+       SqlInfoResult(false /* SQLite 3 does not support schemas */)},
+      {SqlInfoOptions::SqlInfo::SQL_DDL_TABLE, SqlInfoResult(true)},
+      {SqlInfoOptions::SqlInfo::SQL_IDENTIFIER_CASE,
+       SqlInfoResult(int64_t(SqlInfoOptions::SqlSupportedCaseSensitivity::
+                                 SQL_CASE_SENSITIVITY_CASE_INSENSITIVE))},
+      {SqlInfoOptions::SqlInfo::SQL_IDENTIFIER_QUOTE_CHAR,
+       SqlInfoResult(std::string("\""))},
+      {SqlInfoOptions::SqlInfo::SQL_QUOTED_IDENTIFIER_CASE,
+       SqlInfoResult(int64_t(SqlInfoOptions::SqlSupportedCaseSensitivity::
+                                 SQL_CASE_SENSITIVITY_CASE_INSENSITIVE))},
+      {SqlInfoOptions::SqlInfo::SQL_ALL_TABLES_ARE_SELECTABLE, SqlInfoResult(true)},
+      {SqlInfoOptions::SqlInfo::SQL_NULL_ORDERING,
+       SqlInfoResult(
+           int64_t(SqlInfoOptions::SqlNullOrdering::SQL_NULLS_SORTED_AT_START))},
+      {SqlInfoOptions::SqlInfo::SQL_KEYWORDS,
+       SqlInfoResult(std::vector<std::string>({"ABORT",
+                                               "ACTION",
+                                               "ADD",
+                                               "AFTER",
+                                               "ALL",
+                                               "ALTER",
+                                               "ALWAYS",
+                                               "ANALYZE",
+                                               "AND",
+                                               "AS",
+                                               "ASC",
+                                               "ATTACH",
+                                               "AUTOINCREMENT",
+                                               "BEFORE",
+                                               "BEGIN",
+                                               "BETWEEN",
+                                               "BY",
+                                               "CASCADE",
+                                               "CASE",
+                                               "CAST",
+                                               "CHECK",
+                                               "COLLATE",
+                                               "COLUMN",
+                                               "COMMIT",
+                                               "CONFLICT",
+                                               "CONSTRAINT",
+                                               "CREATE",
+                                               "CROSS",
+                                               "CURRENT",
+                                               "CURRENT_DATE",
+                                               "CURRENT_TIME",
+                                               "CURRENT_TIMESTAMP",
+                                               "DATABASE",
+                                               "DEFAULT",
+                                               "DEFERRABLE",
+                                               "DEFERRED",
+                                               "DELETE",
+                                               "DESC",
+                                               "DETACH",
+                                               "DISTINCT",
+                                               "DO",
+                                               "DROP",
+                                               "EACH",
+                                               "ELSE",
+                                               "END",
+                                               "ESCAPE",
+                                               "EXCEPT",
+                                               "EXCLUDE",
+                                               "EXCLUSIVE",
+                                               "EXISTS",
+                                               "EXPLAIN",
+                                               "FAIL",
+                                               "FILTER",
+                                               "FIRST",
+                                               "FOLLOWING",
+                                               "FOR",
+                                               "FOREIGN",
+                                               "FROM",
+                                               "FULL",
+                                               "GENERATED",
+                                               "GLOB",
+                                               "GROUP",
+                                               "GROUPS",
+                                               "HAVING",
+                                               "IF",
+                                               "IGNORE",
+                                               "IMMEDIATE",
+                                               "IN",
+                                               "INDEX",
+                                               "INDEXED",
+                                               "INITIALLY",
+                                               "INNER",
+                                               "INSERT",
+                                               "INSTEAD",
+                                               "INTERSECT",
+                                               "INTO",
+                                               "IS",
+                                               "ISNULL",
+                                               "JOIN",
+                                               "KEY",
+                                               "LAST",
+                                               "LEFT",
+                                               "LIKE",
+                                               "LIMIT",
+                                               "MATCH",
+                                               "MATERIALIZED",
+                                               "NATURAL",
+                                               "NO",
+                                               "NOT",
+                                               "NOTHING",
+                                               "NOTNULL",
+                                               "NULL",
+                                               "NULLS",
+                                               "OF",
+                                               "OFFSET",
+                                               "ON",
+                                               "OR",
+                                               "ORDER",
+                                               "OTHERS",
+                                               "OUTER",
+                                               "OVER",
+                                               "PARTITION",
+                                               "PLAN",
+                                               "PRAGMA",
+                                               "PRECEDING",
+                                               "PRIMARY",
+                                               "QUERY",
+                                               "RAISE",
+                                               "RANGE",
+                                               "RECURSIVE",
+                                               "REFERENCES",
+                                               "REGEXP",
+                                               "REINDEX",
+                                               "RELEASE",
+                                               "RENAME",
+                                               "REPLACE",
+                                               "RESTRICT",
+                                               "RETURNING",
+                                               "RIGHT",
+                                               "ROLLBACK",
+                                               "ROW",
+                                               "ROWS",
+                                               "SAVEPOINT",
+                                               "SELECT",
+                                               "SET",
+                                               "TABLE",
+                                               "TEMP",
+                                               "TEMPORARY",
+                                               "THEN",
+                                               "TIES",
+                                               "TO",
+                                               "TRANSACTION",
+                                               "TRIGGER",
+                                               "UNBOUNDED",
+                                               "UNION",
+                                               "UNIQUE",
+                                               "UPDATE",
+                                               "USING",
+                                               "VACUUM",
+                                               "VALUES",
+                                               "VIEW",
+                                               "VIRTUAL",
+                                               "WHEN",
+                                               "WHERE",
+                                               "WINDOW",
+                                               "WITH",
+                                               "WITHOUT"}))},
+      {SqlInfoOptions::SqlInfo::SQL_NUMERIC_FUNCTIONS,
+       SqlInfoResult(std::vector<std::string>(
+           {"acos",    "acosh", "asin", "asinh",   "atan", "atan2", "atanh", "ceil",
+            "ceiling", "cos",   "cosh", "degrees", "exp",  "floor", "ln",    "log",
+            "log",     "log10", "log2", "mod",     "pi",   "pow",   "power", "radians",
+            "sin",     "sinh",  "sqrt", "tan",     "tanh", "trunc"}))},

Review comment:
       No particular reason! Changed to keep consistency




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-987022815


   Done @lidavidm ! Sorry I forgot those two.
   
   Will update the Java PR now


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r738766458



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+               STATIC_LINK_LIBS
+               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+               GTest::gtest
+               GTest::gmock
+               LABELS
+               "arrow_flight_sql")
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
+                                                  ${GFLAGS_LIBRARIES})
+
+find_package(SQLite3)
+include_directories(${SQLite3_INCLUDE_DIRS})
+
+add_executable(flight_sql_test_server
+               server.cc
+               test_server_cli.cc
+               example/sqlite_statement.cc
+               example/sqlite_statement_batch_reader.cc
+               example/sqlite_server.cc
+               example/sqlite_tables_schema_batch_reader.cpp
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
+target_link_libraries(flight_sql_test_server
+                      PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}
+                              ${SQLite3_LIBRARIES})

Review comment:
       Yes - since the server tests spawn the test server as a subprocess, we need to tell CMake that the test server is a dependency of the test executable. Else, a developer doing a partial build (to save time) via `ninja arrow-flight-sql-test` or similar will find that their test doesn't work, or if this is an incremental build (after making a change), it'll unexpectedly use the old server executable.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-954191248


   Yes - sorry, I've been tied up this week but will get back to this ASAP. Thanks for addressing things. I also want to look at the Protobuf issue still.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756376007



##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.

Review comment:
       Yes! Changed it to a pointer so it can be `nullptr`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756372030



##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.h
##########
@@ -0,0 +1,87 @@
+// 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.
+
+#pragma once
+
+#include "arrow/flight/sql/sql_info_types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+/// \brief Auxiliary class used to populate GetSqlInfo's DenseUnionArray with different
+/// data types.
+class SqlInfoResultAppender {
+ public:
+  /// \brief Appends a string to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::string& value);
+
+  /// \brief Appends a bool to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(bool value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int64_t value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int32_t value);
+
+  /// \brief Appends a string list to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::vector<std::string>& value);
+
+  /// \brief Appends a int32 to int32 list map to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::unordered_map<int32_t, std::vector<int32_t>>& value);

Review comment:
       Hmm, woops, I had misread the snippet above. My bad.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-958183255


   Alright - I can replicate it now, on Ubuntu 20.04: 
   
   This is _without_ any patches - so I think the problem runs even deeper than we expected. I'll do my best to find a solution.
   
   ```
   root@40b933c77b92:/arrow/build# ./debug/arrow-flight-sql-server-test 
   Running main() from /vcpkg/buildtrees/gtest/src/ase-1.11.0-7d339f16d4.clean/googletest/src/gtest_main.cc
   [==========] Running 18 tests from 1 test suite.
   [----------] Global test environment set-up.
   Server running with pid 30605
   Server listening on localhost:58715
   [----------] 18 tests from TestFlightSqlServer
   [ RUN      ] TestFlightSqlServer.TestCommandStatementQuery
   [libprotobuf ERROR /vcpkg/buildtrees/protobuf/src/v3.18.0-44e21376af.clean/src/google/protobuf/descriptor.cc:4121] Invalid proto descriptor for file "google/protobuf/descriptor.proto":
   [libprotobuf ERROR /vcpkg/buildtrees/protobuf/src/v3.18.0-44e21376af.clean/src/google/protobuf/descriptor.cc:4124]   google/protobuf/descriptor.proto: Unrecognized syntax: SELECT * FROM intTable
   [libprotobuf ERROR /vcpkg/buildtrees/protobuf/src/v3.18.0-44e21376af.clean/src/google/protobuf/descriptor.cc:4121] Invalid proto descriptor for file "FlightSql.proto":
   [libprotobuf ERROR /vcpkg/buildtrees/protobuf/src/v3.18.0-44e21376af.clean/src/google/protobuf/descriptor.cc:4124]   arrow.flight.protocol.sql.experimental: ".google.protobuf.MessageOptions" is not defined.
   [libprotobuf FATAL /vcpkg/buildtrees/protobuf/src/v3.18.0-44e21376af.clean/src/google/protobuf/generated_message_reflection.cc:2914] CHECK failed: file != nullptr: 
   unknown file: Failure
   C++ exception with description "CHECK failed: file != nullptr: " thrown in the test body.
   [  FAILED  ] TestFlightSqlServer.TestCommandStatementQuery (3 ms)
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742233667



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       We're defining FlightClientImpl twice and just using the fact that only one definition is visible at a time, trusting that the compiler/linker do the right thing. I'm not sure we can rely on this.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742111758



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Hey @lidavidm ! Can you please clarify?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jcralmeida commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jcralmeida commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746830498



##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_server.cc
##########
@@ -0,0 +1,676 @@
+// 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/api.h>
+#include <arrow/flight/flight_sql/example/sqlite_server.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h>
+#include <arrow/flight/flight_sql/example/sqlite_tables_schema_batch_reader.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const GetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.catalog.has_value()) {
+    table_query << " and catalog_name='" << command.catalog.value() << "'";
+  }
+
+  if (command.schema_filter_pattern.has_value()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern.value()
+                << "'";
+  }
+
+  if (command.table_name_filter_pattern.has_value()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern.value()
+                << "'";
+  }
+
+  if (!command.table_types.empty()) {
+    table_query << " and table_type IN (";
+    size_t size = command.table_types.size();
+    for (size_t i = 0; i < size; i++) {
+      table_query << "'" << command.table_types[i] << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt, FlightMessageReader* reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = static_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = static_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = static_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer = static_cast<StringScalar&>(*holder).value;
+            sqlite3_bind_text(stmt, c + 1, reinterpret_cast<const char*>(buffer->data()),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer = static_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer(sqlite3* db) : db_(db), uuid_generator_({}) {
+  assert(db_);
+}
+
+arrow::Result<std::shared_ptr<SQLiteFlightSqlServer>> SQLiteFlightSqlServer::Create() {
+  sqlite3* db = nullptr;
+
+  if (sqlite3_open(":memory:", &db)) {
+    std::string err_msg = "Can't open database: ";
+    if (db != nullptr) {
+      err_msg += sqlite3_errmsg(db);
+      sqlite3_close(db);
+    } else {
+      err_msg += "Unable to start SQLite. Insufficient memory";
+    }
+
+    return Status::RError(err_msg);
+  }
+
+  std::shared_ptr<SQLiteFlightSqlServer> result(new SQLiteFlightSqlServer(db));

Review comment:
       To use std::make_shared we need to change the constructor to public and this instantiation is inside a Create(). 
   
   Is it bad to not use make_shared? Or do you think we should change the constructor to public and use it anyway




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r762141275



##########
File path: ci/scripts/cpp_build.sh
##########
@@ -70,7 +70,8 @@ cmake \
   -DARROW_EXTRA_ERROR_CONTEXT=${ARROW_EXTRA_ERROR_CONTEXT:-OFF} \
   -DARROW_FILESYSTEM=${ARROW_FILESYSTEM:-ON} \
   -DARROW_FLIGHT=${ARROW_FLIGHT:-OFF} \
-  -DARROW_FUZZING=${ARROW_FUZZING:-OFF} \
+  -DARROW_FLIGHT_SQL=${ARROW_FLIGHT_SQL:-OFF} \
+      -DARROW_FUZZING=${ARROW_FUZZING:-OFF} \

Review comment:
       nit: extra indent?

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -0,0 +1,769 @@
+// 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.h"
+
+#include <arrow/util/logging.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <condition_variable>
+#include <thread>
+
+#include "arrow/flight/api.h"
+#include "arrow/flight/sql/api.h"
+#include "arrow/flight/sql/example/sqlite_server.h"
+#include "arrow/flight/sql/example/sqlite_sql_info.h"
+#include "arrow/flight/test_util.h"
+#include "arrow/flight/types.h"
+#include "arrow/testing/gtest_util.h"
+
+using ::testing::_;
+using ::testing::Ref;
+
+using arrow::internal::checked_cast;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+/// \brief Auxiliary variant visitor used to assert that GetSqlInfo's values are
+/// correctly placed on its DenseUnionArray
+class SqlInfoDenseUnionValidator {
+ private:
+  const DenseUnionScalar& data;
+
+ public:
+  /// \brief Asserts that the current DenseUnionScalar equals to given string value
+  void operator()(const std::string& string_value) const {
+    const auto& scalar = checked_cast<const StringScalar&>(*data.value);
+    ASSERT_EQ(string_value, scalar.ToString());
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given bool value
+  void operator()(const bool bool_value) const {
+    const auto& scalar = checked_cast<const BooleanScalar&>(*data.value);
+    ASSERT_EQ(bool_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int64_t value
+  void operator()(const int64_t bigint_value) const {
+    const auto& scalar = checked_cast<const Int64Scalar&>(*data.value);
+    ASSERT_EQ(bigint_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32_t value
+  void operator()(const int32_t int32_bitmask) const {
+    const auto& scalar = checked_cast<const Int32Scalar&>(*data.value);
+    ASSERT_EQ(int32_bitmask, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given string list
+  void operator()(const std::vector<std::string>& string_list) const {
+    const auto& array = checked_cast<const StringArray&>(
+        *(checked_cast<const ListScalar&>(*data.value).value));
+
+    ASSERT_EQ(string_list.size(), array.length());
+
+    for (size_t index = 0; index < string_list.size(); index++) {
+      ASSERT_EQ(string_list[index], array.GetString(index));
+    }
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32 to int32 list
+  /// map.
+  void operator()(const std::unordered_map<int32_t, std::vector<int32_t>>&
+                      int32_to_int32_list) const {
+    const auto& struct_array = checked_cast<const StructArray&>(
+        *checked_cast<const MapScalar&>(*data.value).value);
+    const auto& keys = checked_cast<const Int32Array&>(*struct_array.field(0));
+    const auto& values = checked_cast<const ListArray&>(*struct_array.field(1));
+
+    // Assert that the given map has the right size
+    ASSERT_EQ(int32_to_int32_list.size(), keys.length());
+
+    // For each element on given MapScalar, assert it matches the argument
+    for (int i = 0; i < keys.length(); i++) {
+      ASSERT_OK_AND_ASSIGN(const auto& key_scalar, keys.GetScalar(i));
+      int32_t sql_info_id = checked_cast<const Int32Scalar&>(*key_scalar).value;
+
+      // Assert the key (SqlInfo id) exists
+      ASSERT_TRUE(int32_to_int32_list.count(sql_info_id));
+
+      const std::vector<int32_t>& expected_int32_list =
+          int32_to_int32_list.at(sql_info_id);
+
+      // Assert the value (int32 list) has the correct size
+      ASSERT_EQ(expected_int32_list.size(), values.value_length(i));
+
+      // For each element on current ListScalar, assert it matches with the argument
+      for (size_t j = 0; j < expected_int32_list.size(); j++) {
+        ASSERT_OK_AND_ASSIGN(auto list_item_scalar,
+                             values.values()->GetScalar(values.value_offset(i) + j));
+        const auto& list_item = checked_cast<const Int32Scalar&>(*list_item_scalar).value;
+        ASSERT_EQ(expected_int32_list[j], list_item);
+      }
+    }
+  }
+
+  explicit SqlInfoDenseUnionValidator(const DenseUnionScalar& data) : data(data) {}
+
+  SqlInfoDenseUnionValidator(const SqlInfoDenseUnionValidator&) = delete;
+  SqlInfoDenseUnionValidator(SqlInfoDenseUnionValidator&&) = delete;
+  SqlInfoDenseUnionValidator& operator=(const SqlInfoDenseUnionValidator&) = delete;
+};
+
+class TestFlightSqlServer : public ::testing::Test {
+ public:
+  std::unique_ptr<FlightSqlClient> sql_client;
+
+  arrow::Result<int64_t> ExecuteCountQuery(const std::string& query) {
+    ARROW_ASSIGN_OR_RAISE(auto flight_info, sql_client->Execute({}, query));
+
+    ARROW_ASSIGN_OR_RAISE(auto stream,
+                          sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+    std::shared_ptr<Table> table;
+    ARROW_RETURN_NOT_OK(stream->ReadAll(&table));
+
+    const std::shared_ptr<Array>& result_array = table->column(0)->chunk(0);
+    ARROW_ASSIGN_OR_RAISE(auto count_scalar, result_array->GetScalar(0));
+
+    return reinterpret_cast<Int64Scalar&>(*count_scalar).value;
+  }
+
+ protected:
+  void SetUp() override {
+    port = GetListenPort();
+    server_thread.reset(new std::thread([&]() { RunServer(); }));
+
+    std::unique_lock<std::mutex> lk(server_ready_m);
+    server_ready_cv.wait(lk);
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << port;
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+
+    ASSERT_OK(server->Shutdown());
+    server_thread->join();
+    server_thread.reset();
+  }
+
+ private:
+  int port;
+  std::shared_ptr<arrow::flight::sql::example::SQLiteFlightSqlServer> server;
+  std::unique_ptr<std::thread> server_thread;
+  std::condition_variable server_ready_cv;
+  std::mutex server_ready_m;
+
+  void RunServer() {
+    arrow::flight::Location location;
+    ARROW_CHECK_OK(arrow::flight::Location::ForGrpcTcp("localhost", port, &location));
+    arrow::flight::FlightServerOptions options(location);
+
+    ARROW_CHECK_OK(example::SQLiteFlightSqlServer::Create().Value(&server));
+
+    ARROW_CHECK_OK(server->Init(options));
+    // Exit with a clean error code (0) on SIGTERM
+    ARROW_CHECK_OK(server->SetShutdownOnSignals({SIGTERM}));
+
+    server_ready_cv.notify_all();
+    ARROW_CHECK_OK(server->Serve());
+  }
+};
+
+TEST_F(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  const auto id_array = ArrayFromJSON(int64(), R"([1, 2, 3, 4])");
+  const auto keyname_array =
+      ArrayFromJSON(utf8(), R"(["one", "zero", "negative one", null])");
+  const auto value_array = ArrayFromJSON(int64(), R"([1, 0, -1, null])");
+  const auto foreignId_array = ArrayFromJSON(int64(), R"([1, 1, 1, null])");
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetTables) {
+  FlightCallOptions options = {};
+  std::string* catalog = nullptr;
+  std::string* schema_filter_pattern = nullptr;
+  std::string* table_filter_pattern = nullptr;
+  bool include_schema = false;
+  std::vector<std::string>* table_types = nullptr;
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables(options, catalog, schema_filter_pattern, table_filter_pattern,
+                            include_schema, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+
+  const auto table_name =
+      ArrayFromJSON(utf8(), R"(["foreignTable", "intTable", "sqlite_sequence"])");
+  const auto table_type = ArrayFromJSON(utf8(), R"(["table", "table", "table"])");
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetTablesWithTableFilter) {
+  FlightCallOptions options = {};
+  std::string* catalog = nullptr;
+  std::string* schema_filter_pattern = nullptr;
+  std::string table_filter_pattern = "int%";
+  bool include_schema = false;
+  std::vector<std::string>* table_types = nullptr;
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables(options, catalog, schema_filter_pattern,
+                            &table_filter_pattern, include_schema, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const auto catalog_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto schema_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto table_name = ArrayFromJSON(utf8(), R"(["intTable"])");
+  const auto table_type = ArrayFromJSON(utf8(), R"(["table"])");
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetTablesWithTableTypesFilter) {
+  FlightCallOptions options = {};
+  std::string* catalog = nullptr;
+  std::string* schema_filter_pattern = nullptr;
+  std::string* table_filter_pattern = nullptr;
+  bool include_schema = false;
+  std::vector<std::string> table_types{"index"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables(options, catalog, schema_filter_pattern, table_filter_pattern,
+                            include_schema, &table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  AssertSchemaEqual(SqlSchema::GetTablesSchema(), table->schema());
+
+  ASSERT_EQ(table->num_rows(), 0);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetTablesWithUnexistenceTableTypeFilter) {
+  FlightCallOptions options = {};
+  std::string* catalog = nullptr;
+  std::string* schema_filter_pattern = nullptr;
+  std::string* table_filter_pattern = nullptr;
+  bool include_schema = false;
+  std::vector<std::string> table_types{"table"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables(options, catalog, schema_filter_pattern, table_filter_pattern,
+                            include_schema, &table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const auto catalog_name = ArrayFromJSON(utf8(), R"([null, null, null])");
+  const auto schema_name = ArrayFromJSON(utf8(), R"([null, null, null])");
+  const auto table_name =
+      ArrayFromJSON(utf8(), R"(["foreignTable", "intTable", "sqlite_sequence"])");
+  const auto table_type = ArrayFromJSON(utf8(), R"(["table", "table", "table"])");
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetTablesWithIncludedSchemas) {
+  FlightCallOptions options = {};
+  std::string* catalog = nullptr;
+  std::string* schema_filter_pattern = nullptr;
+  std::string table_filter_pattern = "int%";
+  bool include_schema = true;
+  std::vector<std::string>* table_types = nullptr;
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables(options, catalog, schema_filter_pattern,
+                            &table_filter_pattern, include_schema, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const auto catalog_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto schema_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto table_name = ArrayFromJSON(utf8(), R"(["intTable"])");
+  const auto table_type = ArrayFromJSON(utf8(), R"(["table"])");
+
+  const std::shared_ptr<Schema> schema_table = arrow::schema(
+      {arrow::field("id", int64(), true), arrow::field("keyName", utf8(), true),
+       arrow::field("value", int64(), true), arrow::field("foreignId", int64(), true)});
+
+  ASSERT_OK_AND_ASSIGN(auto schema_buffer, ipc::SerializeSchema(*schema_table));
+
+  std::shared_ptr<Array> table_schema;
+  ArrayFromVector<BinaryType, std::string>({schema_buffer->ToString()}, &table_schema);
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetTablesSchemaWithIncludedSchema(),
+                  {catalog_name, schema_name, table_name, table_type, table_schema});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetCatalogs) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetCatalogs({}));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema = SqlSchema::GetCatalogsSchema();
+
+  AssertSchemaEqual(expected_schema, table->schema());
+  ASSERT_EQ(0, table->num_rows());
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetDbSchemas) {
+  FlightCallOptions options = {};
+  std::string* catalog = nullptr;
+  std::string* schema_filter_pattern = nullptr;
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetDbSchemas(options, catalog, schema_filter_pattern));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema = SqlSchema::GetDbSchemasSchema();
+
+  AssertSchemaEqual(expected_schema, table->schema());
+  ASSERT_EQ(0, table->num_rows());
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetTableTypes) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetTableTypes({}));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const auto table_type = ArrayFromJSON(utf8(), R"(["table"])");
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetTableTypesSchema(), {table_type});
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandStatementUpdate) {
+  int64_t result;
+  ASSERT_OK_AND_ASSIGN(result,
+                       sql_client->ExecuteUpdate(
+                           {},
+                           "INSERT INTO intTable (keyName, value) VALUES "
+                           "('KEYNAME1', 1001), ('KEYNAME2', 1002), ('KEYNAME3', 1003)"));
+  ASSERT_EQ(3, result);
+
+  ASSERT_OK_AND_ASSIGN(result, sql_client->ExecuteUpdate(
+                                   {},
+                                   "UPDATE intTable SET keyName = 'KEYNAME1' "
+                                   "WHERE keyName = 'KEYNAME2' OR keyName = 'KEYNAME3'"));
+  ASSERT_EQ(2, result);
+
+  ASSERT_OK_AND_ASSIGN(
+      result,
+      sql_client->ExecuteUpdate({}, "DELETE FROM intTable WHERE keyName = 'KEYNAME1'"));
+  ASSERT_EQ(3, result);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandPreparedStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement,
+                       sql_client->Prepare({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto flight_info, prepared_statement->Execute());
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  const auto id_array = ArrayFromJSON(int64(), R"([1, 2, 3, 4])");
+  const auto keyname_array =
+      ArrayFromJSON(utf8(), R"(["one", "zero", "negative one", null])");
+  const auto value_array = ArrayFromJSON(int64(), R"([1, 0, -1, null])");
+  const auto foreignId_array = ArrayFromJSON(int64(), R"([1, 1, 1, null])");
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandPreparedStatementQueryWithParameterBinding) {
+  ASSERT_OK_AND_ASSIGN(
+      auto prepared_statement,
+      sql_client->Prepare({}, "SELECT * FROM intTable WHERE keyName LIKE ?"));
+
+  auto parameter_schema = prepared_statement->parameter_schema();
+
+  const std::shared_ptr<Schema>& expected_parameter_schema =
+      arrow::schema({arrow::field("parameter_1", example::GetUnknownColumnDataType())});
+
+  AssertSchemaEqual(expected_parameter_schema, parameter_schema);
+
+  std::shared_ptr<Array> type_ids = ArrayFromJSON(int8(), R"([0])");
+  std::shared_ptr<Array> offsets = ArrayFromJSON(int32(), R"([0])");
+  std::shared_ptr<Array> string_array = ArrayFromJSON(utf8(), R"(["%one"])");
+  std::shared_ptr<Array> bytes_array = ArrayFromJSON(binary(), R"([])");
+  std::shared_ptr<Array> bigint_array = ArrayFromJSON(int64(), R"([])");
+  std::shared_ptr<Array> double_array = ArrayFromJSON(float64(), R"([])");
+
+  ASSERT_OK_AND_ASSIGN(
+      auto parameter_1_array,
+      DenseUnionArray::Make(*type_ids, *offsets,
+                            {string_array, bytes_array, bigint_array, double_array},
+                            {"string", "bytes", "bigint", "double"}, {0, 1, 2, 3}));
+
+  const std::shared_ptr<RecordBatch>& record_batch =
+      RecordBatch::Make(parameter_schema, 1, {parameter_1_array});
+
+  ASSERT_OK(prepared_statement->SetParameters(record_batch));
+
+  ASSERT_OK_AND_ASSIGN(auto flight_info, prepared_statement->Execute());
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  const auto id_array = ArrayFromJSON(int64(), R"([1, 3])");
+  const auto keyname_array = ArrayFromJSON(utf8(), R"(["one", "negative one"])");
+  const auto value_array = ArrayFromJSON(int64(), R"([1, -1])");
+  const auto foreignId_array = ArrayFromJSON(int64(), R"([1, 1])");
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandPreparedStatementUpdateWithParameterBinding) {
+  ASSERT_OK_AND_ASSIGN(
+      auto prepared_statement,
+      sql_client->Prepare(
+          {}, "INSERT INTO INTTABLE (keyName, value) VALUES ('new_value', ?)"));
+
+  auto parameter_schema = prepared_statement->parameter_schema();
+
+  const std::shared_ptr<Schema>& expected_parameter_schema =
+      arrow::schema({arrow::field("parameter_1", example::GetUnknownColumnDataType())});
+
+  AssertSchemaEqual(expected_parameter_schema, parameter_schema);
+
+  std::shared_ptr<Array> type_ids = ArrayFromJSON(int8(), R"([2])");
+  std::shared_ptr<Array> offsets = ArrayFromJSON(int32(), R"([0])");
+  std::shared_ptr<Array> string_array = ArrayFromJSON(utf8(), R"([])");
+  std::shared_ptr<Array> bytes_array = ArrayFromJSON(binary(), R"([])");
+  std::shared_ptr<Array> bigint_array = ArrayFromJSON(int64(), R"([999])");
+  std::shared_ptr<Array> double_array = ArrayFromJSON(float64(), R"([])");
+
+  ASSERT_OK_AND_ASSIGN(
+      auto parameter_1_array,
+      DenseUnionArray::Make(*type_ids, *offsets,
+                            {string_array, bytes_array, bigint_array, double_array},
+                            {"string", "bytes", "bigint", "double"}, {0, 1, 2, 3}));
+
+  const std::shared_ptr<RecordBatch>& record_batch =
+      RecordBatch::Make(parameter_schema, 1, {parameter_1_array});
+
+  ASSERT_OK(prepared_statement->SetParameters(record_batch));
+
+  ASSERT_OK_AND_EQ(4, ExecuteCountQuery("SELECT COUNT(*) FROM intTable"));
+
+  ASSERT_OK_AND_EQ(1, prepared_statement->ExecuteUpdate());
+
+  ASSERT_OK_AND_EQ(5, ExecuteCountQuery("SELECT COUNT(*) FROM intTable"));
+
+  ASSERT_OK_AND_EQ(1, sql_client->ExecuteUpdate(
+                          {}, "DELETE FROM intTable WHERE keyName = 'new_value'"));
+
+  ASSERT_OK_AND_EQ(4, ExecuteCountQuery("SELECT COUNT(*) FROM intTable"));
+}
+
+TEST_F(TestFlightSqlServer, TestCommandPreparedStatementUpdate) {
+  ASSERT_OK_AND_ASSIGN(
+      auto prepared_statement,
+      sql_client->Prepare(
+          {}, "INSERT INTO INTTABLE (keyName, value) VALUES ('new_value', 999)"));
+
+  ASSERT_OK_AND_EQ(4, ExecuteCountQuery("SELECT COUNT(*) FROM intTable"));
+
+  ASSERT_OK_AND_EQ(1, prepared_statement->ExecuteUpdate());
+
+  ASSERT_OK_AND_EQ(5, ExecuteCountQuery("SELECT COUNT(*) FROM intTable"));
+
+  ASSERT_OK_AND_EQ(1, sql_client->ExecuteUpdate(
+                          {}, "DELETE FROM intTable WHERE keyName = 'new_value'"));
+
+  ASSERT_OK_AND_EQ(4, ExecuteCountQuery("SELECT COUNT(*) FROM intTable"));
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetPrimaryKeys) {
+  FlightCallOptions options = {};
+  TableRef table_ref = {util::nullopt, util::nullopt, "int%"};
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetPrimaryKeys(options, table_ref));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const auto catalog_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto schema_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto key_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto table_name = ArrayFromJSON(utf8(), R"(["intTable"])");
+  const auto column_name = ArrayFromJSON(utf8(), R"(["id"])");
+  const auto key_sequence = ArrayFromJSON(int64(), R"([1])");
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetPrimaryKeysSchema(),
+      {catalog_name, schema_name, table_name, column_name, key_sequence, key_name});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetImportedKeys) {
+  FlightCallOptions options = {};
+  TableRef table_ref = {util::nullopt, util::nullopt, "intTable"};
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetImportedKeys(options, table_ref));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const auto pk_catalog_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto pk_schema_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto pk_table_name = ArrayFromJSON(utf8(), R"(["foreignTable"])");
+  const auto pk_column_name = ArrayFromJSON(utf8(), R"(["id"])");
+  const auto fk_catalog_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto fk_schema_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto fk_table_name = ArrayFromJSON(utf8(), R"(["intTable"])");
+  const auto fk_column_name = ArrayFromJSON(utf8(), R"(["foreignId"])");
+  const auto key_sequence = ArrayFromJSON(int32(), R"([0])");
+  const auto fk_key_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto pk_key_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto update_rule = ArrayFromJSON(uint8(), R"([3])");
+  const auto delete_rule = ArrayFromJSON(uint8(), R"([3])");
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetImportedKeysSchema(),
+                  {pk_catalog_name, pk_schema_name, pk_table_name, pk_column_name,
+                   fk_catalog_name, fk_schema_name, fk_table_name, fk_column_name,
+                   key_sequence, fk_key_name, pk_key_name, update_rule, delete_rule});
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetExportedKeys) {
+  FlightCallOptions options = {};
+  TableRef table_ref = {util::nullopt, util::nullopt, "foreignTable"};
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetExportedKeys(options, table_ref));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const auto pk_catalog_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto pk_schema_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto pk_table_name = ArrayFromJSON(utf8(), R"(["foreignTable"])");
+  const auto pk_column_name = ArrayFromJSON(utf8(), R"(["id"])");
+  const auto fk_catalog_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto fk_schema_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto fk_table_name = ArrayFromJSON(utf8(), R"(["intTable"])");
+  const auto fk_column_name = ArrayFromJSON(utf8(), R"(["foreignId"])");
+  const auto key_sequence = ArrayFromJSON(int32(), R"([0])");
+  const auto fk_key_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto pk_key_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto update_rule = ArrayFromJSON(uint8(), R"([3])");
+  const auto delete_rule = ArrayFromJSON(uint8(), R"([3])");
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetExportedKeysSchema(),
+                  {pk_catalog_name, pk_schema_name, pk_table_name, pk_column_name,
+                   fk_catalog_name, fk_schema_name, fk_table_name, fk_column_name,
+                   key_sequence, fk_key_name, pk_key_name, update_rule, delete_rule});
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetCrossReference) {
+  FlightCallOptions options = {};
+  TableRef pk_table_ref = {util::nullopt, util::nullopt, "foreignTable"};
+  TableRef fk_table_ref = {util::nullopt, util::nullopt, "intTable"};
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetCrossReference(
+                                             options, pk_table_ref, fk_table_ref));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const auto pk_catalog_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto pk_schema_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto pk_table_name = ArrayFromJSON(utf8(), R"(["foreignTable"])");
+  const auto pk_column_name = ArrayFromJSON(utf8(), R"(["id"])");
+  const auto fk_catalog_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto fk_schema_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto fk_table_name = ArrayFromJSON(utf8(), R"(["intTable"])");
+  const auto fk_column_name = ArrayFromJSON(utf8(), R"(["foreignId"])");
+  const auto key_sequence = ArrayFromJSON(int32(), R"([0])");
+  const auto fk_key_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto pk_key_name = ArrayFromJSON(utf8(), R"([null])");
+  const auto update_rule = ArrayFromJSON(uint8(), R"([3])");
+  const auto delete_rule = ArrayFromJSON(uint8(), R"([3])");
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetCrossReferenceSchema(),
+                  {pk_catalog_name, pk_schema_name, pk_table_name, pk_column_name,
+                   fk_catalog_name, fk_schema_name, fk_table_name, fk_column_name,
+                   key_sequence, fk_key_name, pk_key_name, update_rule, delete_rule});
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetSqlInfo) {
+  const auto& sql_info_expected_results = sql::example::GetSqlInfoResultMap();
+  std::vector<int> sql_info_ids;
+  sql_info_ids.reserve(sql_info_expected_results.size());
+  for (const auto& sql_info_expected_result : sql_info_expected_results) {
+    sql_info_ids.push_back(sql_info_expected_result.first);
+  }
+
+  FlightCallOptions call_options;
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetSqlInfo(call_options, sql_info_ids));
+  ASSERT_OK_AND_ASSIGN(
+      auto reader, sql_client->DoGet(call_options, flight_info->endpoints()[0].ticket));
+  std::shared_ptr<Table> results;
+  ASSERT_OK(reader->ReadAll(&results));
+  ASSERT_EQ(2, results->num_columns());
+  ASSERT_EQ(sql_info_ids.size(), results->num_rows());
+  const auto& col_name = results->column(0);
+  const auto& col_value = results->column(1);
+  for (int32_t i = 0; i < col_name->num_chunks(); i++) {
+    const auto* col_name_chunk_data =
+        col_name->chunk(i)->data()->GetValuesSafe<int32_t>(1);
+    const auto& col_value_chunk = col_value->chunk(i);
+    for (int64_t row = 0; row < col_value->length(); row++) {
+      ASSERT_OK_AND_ASSIGN(const auto& scalar, col_value_chunk->GetScalar(row));
+      const SqlInfoDenseUnionValidator validator(
+          reinterpret_cast<const DenseUnionScalar&>(*scalar));
+      const auto& expected_result =
+          sql_info_expected_results.at(col_name_chunk_data[row]);
+      arrow::util::visit(validator, expected_result);
+    }
+  }
+}
+
+TEST_F(TestFlightSqlServer, TestCommandGetSqlInfoNoInfo) {
+  FlightCallOptions call_options;
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetSqlInfo(call_options, {999999}));
+  auto result = sql_client->DoGet(call_options, flight_info->endpoints()[0].ticket);

Review comment:
       note: you can make this `ASSERT_RAISES_WITH_MESSAGE_THAT(KeyError, ::testing::HasSubstr(...), sql_client->DoGet(...));`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r762146369



##########
File path: cpp/src/arrow/flight/sql/CMakeLists.txt
##########
@@ -66,36 +66,34 @@ else()
                                       ${ARROW_TEST_LINK_LIBS})
 endif()
 
-add_arrow_test(flight_sql_test
-               SOURCES
-               client_test.cc
-               server_test.cc
-               example/sqlite_sql_info.cc
-               STATIC_LINK_LIBS
-               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
-               LABELS
-               "arrow_flight_sql")
-
 # Build test server for unit tests
 if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
   find_package(SQLite3Alt REQUIRED)
 
-  add_executable(flight_sql_test_server
-                 test_server_cli.cc
-                 example/sqlite_sql_info.cc
-                 example/sqlite_statement.cc
-                 example/sqlite_statement_batch_reader.cc
-                 example/sqlite_server.cc
-                 example/sqlite_tables_schema_batch_reader.cc)
+  set(flight_sql_test_server_SRCS

Review comment:
       Ah, my bad, somehow I got mixed up and thought the server sources were getting built into the client CLI. This looks fine.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r747063388



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       @rafael-telles how about this? This links the tests statically if we have static protobuf. The .so is still a landmine for users, though...
   
   ```diff
   --- a/cpp/src/arrow/flight/CMakeLists.txt
   +++ b/cpp/src/arrow/flight/CMakeLists.txt
   @@ -25,7 +25,18 @@ if(WIN32)
      list(APPEND ARROW_FLIGHT_LINK_LIBS ws2_32.lib)
    endif()
    
   -if(ARROW_TEST_LINKAGE STREQUAL "static")
   +set(ARROW_FLIGHT_TEST_LINKAGE "${ARROW_TEST_LINKAGE}" PARENT_SCOPE)
   +if (Protobuf_USE_STATIC_LIBS)
   +  message(STATUS "Linking Arrow Flight tests statically due to static Protobuf")
   +  set(ARROW_FLIGHT_TEST_LINKAGE "static" PARENT_SCOPE)
   +endif()
   +if (NOT ARROW_GRPC_USE_SHARED)
   +  message(STATUS "Linking Arrow Flight tests statically due to static gRPC")
   +  set(ARROW_FLIGHT_TEST_LINKAGE "static" PARENT_SCOPE)
   +endif()
   +
   +
   +if(ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static")
      set(ARROW_FLIGHT_TEST_LINK_LIBS
          arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
          ${ARROW_TEST_LINK_LIBS})
   diff --git a/cpp/src/arrow/flight/flight_sql/CMakeLists.txt b/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   index fd28559a9..f2bbb8f9b 100644
   --- a/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   +++ b/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   @@ -36,7 +36,7 @@ set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENER
    
    add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
    
   -set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
   +set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
    
    add_arrow_lib(arrow_flight_sql
                  CMAKE_PACKAGE_NAME
   @@ -58,7 +58,7 @@ add_arrow_lib(arrow_flight_sql
                  STATIC_LINK_LIBS
                  arrow_flight_static)
    
   -if(ARROW_TEST_LINKAGE STREQUAL "static")
   +if(ARROW_FLIGHT_TEST_LINKAGE STREQUAL "static")
      set(ARROW_FLIGHT_TEST_LINK_LIBS
          arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
          ${ARROW_TEST_LINK_LIBS})
   @@ -81,7 +81,6 @@ add_arrow_test(flight_sql_test
                   SOURCES
                   client_test.cc
                   server_test.cc
   -               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
                   STATIC_LINK_LIBS
                   ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
                   LABELS
   @@ -97,8 +96,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
                     example/sqlite_statement.cc
                     example/sqlite_statement_batch_reader.cc
                     example/sqlite_server.cc
   -                 example/sqlite_tables_schema_batch_reader.cc
   -                 "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
   +                 example/sqlite_tables_schema_batch_reader.cc)
      target_link_libraries(flight_sql_test_server
                            PRIVATE ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS} ${GFLAGS_LIBRARIES}
                                    ${SQLite3_LIBRARIES})
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r748525998



##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_server.h
##########
@@ -0,0 +1,351 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight_sql/FlightSql.pb.h"
+#include "arrow/flight/flight_sql/example/sqlite_statement.h"
+#include "arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight_sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+namespace flight_sql_pb = arrow::flight::protocol::sql;
+
+/// \brief Gets the mapping from SQL info ids to SqlInfoResult instances.
+/// \return the cache.
+inline sql_info_id_to_result_t GetSqlInfoIdToResult() {

Review comment:
       Ah, alright then.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jcralmeida commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jcralmeida commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746825327



##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_server.cc
##########
@@ -0,0 +1,676 @@
+// 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/api.h>
+#include <arrow/flight/flight_sql/example/sqlite_server.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h>
+#include <arrow/flight/flight_sql/example/sqlite_tables_schema_batch_reader.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const GetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.catalog.has_value()) {
+    table_query << " and catalog_name='" << command.catalog.value() << "'";
+  }
+
+  if (command.schema_filter_pattern.has_value()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern.value()
+                << "'";
+  }
+
+  if (command.table_name_filter_pattern.has_value()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern.value()
+                << "'";
+  }
+
+  if (!command.table_types.empty()) {
+    table_query << " and table_type IN (";
+    size_t size = command.table_types.size();
+    for (size_t i = 0; i < size; i++) {
+      table_query << "'" << command.table_types[i] << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt, FlightMessageReader* reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = static_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = static_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = static_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer = static_cast<StringScalar&>(*holder).value;
+            sqlite3_bind_text(stmt, c + 1, reinterpret_cast<const char*>(buffer->data()),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer = static_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer(sqlite3* db) : db_(db), uuid_generator_({}) {
+  assert(db_);
+}
+
+arrow::Result<std::shared_ptr<SQLiteFlightSqlServer>> SQLiteFlightSqlServer::Create() {
+  sqlite3* db = nullptr;
+
+  if (sqlite3_open(":memory:", &db)) {
+    std::string err_msg = "Can't open database: ";
+    if (db != nullptr) {
+      err_msg += sqlite3_errmsg(db);
+      sqlite3_close(db);
+    } else {
+      err_msg += "Unable to start SQLite. Insufficient memory";
+    }
+
+    return Status::RError(err_msg);
+  }
+
+  std::shared_ptr<SQLiteFlightSqlServer> result(new SQLiteFlightSqlServer(db));
+
+  ARROW_UNUSED(result->ExecuteSql(R"(

Review comment:
       Fixed, we didn't noticed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-977926275


   Unfortunately SQL databases also have a distinct concept of "schema". Perhaps we could refer to them as 'DbSchema'/'db_schema' or something if that helps?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r757097682



##########
File path: cpp/src/arrow/flight/sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,177 @@
+// 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/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/builder.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                             \
+  case TYPE_CLASS##Type::type_id: {                                               \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                               \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);              \
+    if (string == nullptr) {                                                      \
+      ARROW_RETURN_NOT_OK(                                                        \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());        \
+      break;                                                                      \
+    }                                                                             \
+    ARROW_RETURN_NOT_OK(                                                          \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes)); \
+    break;                                                                        \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK(                                                             \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());             \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes)); \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                        \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);             \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \

Review comment:
       Ops, that was wrong! Thanks for pointing it out




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r736846655



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \param schema   The parameter schema from the query.
+  /// \return         Status.
+  Status GetParameterSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \param schema   The ResultSet schema from the query.
+  /// \return         Status.
+  Status GetResultSetSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding_   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.
+  /// \return Status.
+  Status Close();
+
+  /// \brief Checks if the prepared statement is closed.
+  /// \return The state of the prepared statement.
+  bool IsClosed() const;
+};
+
+/// \brief Flight client with Flight SQL semantics.
+template <class T = arrow::flight::FlightClient>
+class FlightSqlClientT {
+ public:
+  explicit FlightSqlClientT(std::unique_ptr<T>& client);
+
+  ~FlightSqlClientT();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset
+  /// \return Status.
+  Status Execute(const FlightCallOptions& options, const std::string& query,
+                 std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] rows        The quantity of rows affected by the operation.
+  /// \return Status.
+  Status ExecuteUpdate(const FlightCallOptions& options, const std::string& query,
+                       int64_t* rows) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset.
+  /// \return Status.
+  Status GetCatalogs(const FlightCallOptions& options,
+                     std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \param[out] flight_info           The FlightInfo describing where to access the
+  ///                                   dataset.
+  /// \return Status.
+  Status GetSchemas(const FlightCallOptions& options, const std::string* catalog,
+                    const std::string* schema_filter_pattern,
+                    std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \param[out] stream the returned RecordBatchReader
+  /// \return Status
+  Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream) const;

Review comment:
       @lidavidm we did this because it failed when calling methods on `const FlightSqlClient&`:
   
   ```
   'this' argument to member function 'DoGet' has type 'const arrow::flight::sql::FlightSqlClient', but function is not marked const
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735811559



##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,404 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/server.h>
+#include <google/protobuf/any.pb.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlServerBase : public FlightServerBase {
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType FLIGHT_SQL_CREATE_PREPARED_STATEMENT =
+      ActionType{.type = "CreatePreparedStatement",
+                 .description =
+                     "Creates a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionCreatePreparedStatementRequest\n"
+                     "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType FLIGHT_SQL_CLOSE_PREPARED_STATEMENT =
+      ActionType{.type = "ClosePreparedStatement",
+                 .description =
+                     "Closes a reusable prepared statement resource on the server.\n"
+                     "Request Message: ActionClosePreparedStatementRequest\n"
+                     "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] command      The CommandStatementQuery object containing the SQL
+  ///                         statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const pb::sql::CommandStatementQuery& command,

Review comment:
       That sounds good to me. Sorry, I was debating it because it's also quite tedious to do, but I think it's best if we can avoid exposing Protobuf.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735859354



##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,172 @@
+// 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/flight-sql/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);                   \
+    if (string == nullptr) {                                                           \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes));          \
+    break;                                                                             \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes));     \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                    \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);                         \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define FLOAT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    double value = sqlite3_column_double(STMT, COLUMN);                               \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define MAX_BATCH_SIZE 1024
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<Schema> SqliteStatementBatchReader::schema() const { return schema_; }
+
+SqliteStatementBatchReader::SqliteStatementBatchReader(
+    std::shared_ptr<SqliteStatement> statement, std::shared_ptr<Schema> schema)
+    : statement_(std::move(statement)), schema_(std::move(schema)) {

Review comment:
       Fixing this appears to fix the tests.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734742855



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       Yes, that was templated to support putting a mock client in for tests.
   
   If I'm reading this right, the suggestion would be to have:
   - client.h methods just be declarations and take in a FlightClientImpl*
   - create a client_internal.h that defines what FlightClientImpl can do.
   - Provide two .cc's that implement FlightClientImpl, one with the logic for a real FlightClient and one for a mock FlightClient. The .cc used will depend on if building for release or for tests.
   - Provide a .cc for FlightSqlClient that invokes the FlightClientImpl.
   
   This should let us abstract the implementation details for FlightSqlClient while avoiding virtual functions for performance.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-951210329


   So far I've not been able to reproduce the problem with Protobuf, this is with a dynamically linked build where the generated protobuf sources are compiled into libarrow_flight_sql.so. (A fully statically linked build fails for me while building gRPC; a build where only libarrow_XXX.a are statically linked does pass tests.) 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-956457180


   > Regarding the Protobuf issue: I switched to vcpkg as that appears to be what you use, but I can't replicate still. What OS and compiler are you using?
   
   @lidavidm , yes, I am using vcpkg.
   My OS is Linux Mint 20.2, 
   cmake version 3.16.3
   g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
   gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
   
   Thanks for your help @lidavidm , please let me know if any other info is helpful! Working on the other comments
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r740377479



##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>

Review comment:
       No! Sorry for the mistake




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-958006483


   Thanks. I'm still digging at this. vcpkg made a change recently that breaks the build, so I need to figure out that first…


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742234687



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       That said, my understanding of this is shaky and maybe there is a good justification for why this works.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742350786



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Oops, didn't see your last comment!
   I thought that as it was statically linking libarrow_flight_sql(containing client_internal.cc) when building client_test.cc it could be a problem.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-987946939


   Looks like all tests are passing here and on the Java PR! Thanks to Rafael & co. for iterating on things and to @pitrou, @emkornfield, &co. for reviews. 
   
   Unless there are further comments, I'll submit the vote to the ML later today (EST).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756032164



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name, then schema_name.
+ */
+message CommandGetSchemas {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, the pattern will not be used to narrow the search.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+}
+
+/*
+ * Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  table_type: utf8 not null,
+ *  [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema,
+ *                                           it is serialized as an IPC message.)
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, then table_type, followed by table_schema if requested.
+ */
+message CommandGetTables {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, all schemas matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+
+  /*
+   * Specifies a filter pattern for tables to search for.
+   * When no table_name_filter_pattern is provided, all tables matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string table_name_filter_pattern = 3;
+
+  // Specifies a filter of table types which must match.
+  repeated string table_types = 4;
+
+  // Specifies if the schema should be returned for found tables.
+  bool include_schema = 5;
+}
+
+/*
+ * Represents a request to retrieve the list of table types on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  table_type: utf8 not null
+ * >
+ * The returned data should be ordered by table_type.
+ */
+message CommandGetTableTypes {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the primary keys of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  column_name: utf8 not null,
+ *  key_name: utf8,
+ *  key_sequence: int not null
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, key_name, then key_sequence.
+ */
+message CommandGetPrimaryKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the table to get the primary keys for.
+  string table = 3;
+}
+
+enum UpdateDeleteRules {
+  CASCADE = 0;
+  RESTRICT = 1;
+  SET_NULL = 2;
+  NO_ACTION = 3;
+  SET_DEFAULT = 4;
+}
+
+/*
+ * Represents a request to retrieve a description of the foreign key columns that reference the given table's
+ * primary key columns (the foreign keys exported by a table) of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by fk_catalog_name, fk_schema_name, fk_table_name, fk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions declared on UpdateDeleteRules enum.
+ */
+message CommandGetExportedKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the foreign key table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the foreign key table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the foreign key table to get the foreign keys for.
+  string table = 3;
+}
+
+/*
+ * Represents a request to retrieve the foreign keys of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by pk_catalog_name, pk_schema_name, pk_table_name, pk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions:
+ *    - 0 = CASCADE
+ *    - 1 = RESTRICT
+ *    - 2 = SET NULL
+ *    - 3 = NO ACTION
+ *    - 4 = SET DEFAULT
+ */
+message CommandGetImportedKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the primary key table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the primary key table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the primary key table to get the foreign keys for.
+  string table = 3;
+}
+
+/*
+ * Represents a request to retrieve a description of the foreign key columns in the given foreign key table that
+ * reference the primary key or the columns representing a unique constraint of the parent table (could be the same
+ * or a different table) on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by pk_catalog_name, pk_schema_name, pk_table_name, pk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions:
+ *    - 0 = CASCADE
+ *    - 1 = RESTRICT
+ *    - 2 = SET NULL
+ *    - 3 = NO ACTION
+ *    - 4 = SET DEFAULT
+ */
+message CommandGetCrossReference {
+  option (experimental) = true;
+
+  /**
+   * The catalog name where the parent table is.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string pk_catalog = 1;
+
+  /**
+   * The Schema name where the parent table is.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string pk_schema = 2;
+
+  /**
+   * The parent table name. It cannot be null.
+   */
+  string pk_table = 3;
+
+  /**
+   * The catalog name where the foreign table is.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string fk_catalog = 4;
+
+  /**
+   * The schema name where the foreign table is.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string fk_schema = 5;
+
+  /**
+   * The foreign table name. It cannot be null.
+   */
+  string fk_table = 6;
+}
+
+// SQL Execution Action Messages
+
+/*
+ * Request message for the "CreatePreparedStatement" action on a Flight SQL enabled backend.
+ */
+message ActionCreatePreparedStatementRequest {
+  option (experimental) = true;
+
+  // The valid SQL string to create a prepared statement for.
+  string query = 1;
+}
+
+/*
+ * Wrap the result of a "GetPreparedStatement" action.
+ *
+ * The resultant PreparedStatement can be closed either:
+ * - Manually, through the "ClosePreparedStatement" action;
+ * - Automatically, by a server timeout.
+ */
+message ActionCreatePreparedStatementResult {
+  option (experimental) = true;
+
+  // Opaque handle for the prepared statement on the server.
+  bytes prepared_statement_handle = 1;
+
+  // If a result set generating query was provided, dataset_schema contains the 
+  // schema of the dataset as described in Schema.fbs::Schema, it is serialized as an IPC message.
+  bytes dataset_schema = 2;
+
+  // If the query provided contained parameters, parameter_schema contains the 
+  // schema of the expected parameters as described in Schema.fbs::Schema, it is serialized as an IPC message.
+  bytes parameter_schema = 3;
+}
+
+/*
+ * Request message for the "ClosePreparedStatement" action on a Flight SQL enabled backend.
+ * Closes server resources associated with the prepared statement handle.
+ */
+message ActionClosePreparedStatementRequest {
+  option (experimental) = true;
+
+  // Opaque handle for the prepared statement on the server.
+  bytes prepared_statement_handle = 1;
+}
+
+
+// SQL Execution Messages.
+
+/*
+ * Represents a SQL query. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the query.
+ */
+message CommandStatementQuery {
+  option (experimental) = true;
+
+  // The SQL syntax.
+  string query = 1;
+}
+
+/**
+ * Represents a ticket resulting from GetFlightInfo with a CommandStatementQuery.
+ * This should be treated as an opaque value, that is, clients should not attempt to parse this.
+ */
+message TicketStatementQuery {
+  option (experimental) = true;
+
+  // Unique identifier for the instance of the statement to execute.
+  bytes statement_handle = 1;

Review comment:
       Can you also add that to the comment/docstring?
   
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r752341395



##########
File path: cpp/src/arrow/CMakeLists.txt
##########
@@ -726,6 +726,10 @@ if(ARROW_FLIGHT)
   add_subdirectory(flight)
 endif()
 
+if(ARROW_FLIGHT_SQL)
+  add_subdirectory(flight/flight_sql)

Review comment:
       Why not `flight/sql`?

##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.

Review comment:
       What is a catalog? Is it like a table or a database?

##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;

Review comment:
       Hmm... what does this mean in protobuf parlance?

##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name, then schema_name.
+ */
+message CommandGetSchemas {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, the pattern will not be used to narrow the search.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+}
+
+/*
+ * Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  table_type: utf8 not null,
+ *  [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema,
+ *                                           it is serialized as an IPC message.)
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, then table_type, followed by table_schema if requested.
+ */
+message CommandGetTables {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, all schemas matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+
+  /*
+   * Specifies a filter pattern for tables to search for.
+   * When no table_name_filter_pattern is provided, all tables matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string table_name_filter_pattern = 3;
+
+  // Specifies a filter of table types which must match.
+  repeated string table_types = 4;
+
+  // Specifies if the schema should be returned for found tables.
+  bool include_schema = 5;
+}
+
+/*
+ * Represents a request to retrieve the list of table types on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  table_type: utf8 not null
+ * >
+ * The returned data should be ordered by table_type.
+ */
+message CommandGetTableTypes {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the primary keys of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  column_name: utf8 not null,
+ *  key_name: utf8,
+ *  key_sequence: int not null
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, key_name, then key_sequence.
+ */
+message CommandGetPrimaryKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the table to get the primary keys for.
+  string table = 3;
+}
+
+enum UpdateDeleteRules {
+  CASCADE = 0;
+  RESTRICT = 1;
+  SET_NULL = 2;
+  NO_ACTION = 3;
+  SET_DEFAULT = 4;
+}
+
+/*
+ * Represents a request to retrieve a description of the foreign key columns that reference the given table's
+ * primary key columns (the foreign keys exported by a table) of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by fk_catalog_name, fk_schema_name, fk_table_name, fk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions declared on UpdateDeleteRules enum.
+ */
+message CommandGetExportedKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the foreign key table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the foreign key table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the foreign key table to get the foreign keys for.
+  string table = 3;
+}
+
+/*
+ * Represents a request to retrieve the foreign keys of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by pk_catalog_name, pk_schema_name, pk_table_name, pk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions:
+ *    - 0 = CASCADE
+ *    - 1 = RESTRICT
+ *    - 2 = SET NULL
+ *    - 3 = NO ACTION
+ *    - 4 = SET DEFAULT
+ */
+message CommandGetImportedKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the primary key table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the primary key table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the primary key table to get the foreign keys for.
+  string table = 3;
+}
+
+/*
+ * Represents a request to retrieve a description of the foreign key columns in the given foreign key table that
+ * reference the primary key or the columns representing a unique constraint of the parent table (could be the same
+ * or a different table) on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by pk_catalog_name, pk_schema_name, pk_table_name, pk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions:
+ *    - 0 = CASCADE
+ *    - 1 = RESTRICT
+ *    - 2 = SET NULL
+ *    - 3 = NO ACTION
+ *    - 4 = SET DEFAULT
+ */
+message CommandGetCrossReference {
+  option (experimental) = true;
+
+  /**
+   * The catalog name where the parent table is.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string pk_catalog = 1;
+
+  /**
+   * The Schema name where the parent table is.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string pk_schema = 2;
+
+  /**
+   * The parent table name. It cannot be null.
+   */
+  string pk_table = 3;
+
+  /**
+   * The catalog name where the foreign table is.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string fk_catalog = 4;
+
+  /**
+   * The schema name where the foreign table is.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string fk_schema = 5;
+
+  /**
+   * The foreign table name. It cannot be null.
+   */
+  string fk_table = 6;
+}
+
+// SQL Execution Action Messages
+
+/*
+ * Request message for the "CreatePreparedStatement" action on a Flight SQL enabled backend.
+ */
+message ActionCreatePreparedStatementRequest {
+  option (experimental) = true;
+
+  // The valid SQL string to create a prepared statement for.
+  string query = 1;
+}
+
+/*
+ * Wrap the result of a "GetPreparedStatement" action.
+ *
+ * The resultant PreparedStatement can be closed either:
+ * - Manually, through the "ClosePreparedStatement" action;
+ * - Automatically, by a server timeout.
+ */
+message ActionCreatePreparedStatementResult {
+  option (experimental) = true;
+
+  // Opaque handle for the prepared statement on the server.
+  bytes prepared_statement_handle = 1;
+
+  // If a result set generating query was provided, dataset_schema contains the 
+  // schema of the dataset as described in Schema.fbs::Schema, it is serialized as an IPC message.
+  bytes dataset_schema = 2;
+
+  // If the query provided contained parameters, parameter_schema contains the 
+  // schema of the expected parameters as described in Schema.fbs::Schema, it is serialized as an IPC message.
+  bytes parameter_schema = 3;
+}
+
+/*
+ * Request message for the "ClosePreparedStatement" action on a Flight SQL enabled backend.
+ * Closes server resources associated with the prepared statement handle.
+ */
+message ActionClosePreparedStatementRequest {
+  option (experimental) = true;
+
+  // Opaque handle for the prepared statement on the server.
+  bytes prepared_statement_handle = 1;
+}
+
+
+// SQL Execution Messages.
+
+/*
+ * Represents a SQL query. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the query.
+ */
+message CommandStatementQuery {
+  option (experimental) = true;
+
+  // The SQL syntax.
+  string query = 1;
+}
+
+/**
+ * Represents a ticket resulting from GetFlightInfo with a CommandStatementQuery.
+ * This should be treated as an opaque value, that is, clients should not attempt to parse this.
+ */
+message TicketStatementQuery {
+  option (experimental) = true;
+
+  // Unique identifier for the instance of the statement to execute.
+  bytes statement_handle = 1;

Review comment:
       What is the lifetime of this handle?

##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 

Review comment:
       Is there a good reason for this scheme? This seems to mean that any new standard info element needs a new enum to be committed here and available at compile-time.
   
   It seems it would be much more flexible to take an arbitrary string and have a separate document listing well-known info element names.

##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null

Review comment:
       Hmm, what is a schema name?

##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name, then schema_name.
+ */
+message CommandGetSchemas {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, the pattern will not be used to narrow the search.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+}
+
+/*
+ * Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  table_type: utf8 not null,
+ *  [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema,
+ *                                           it is serialized as an IPC message.)
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, then table_type, followed by table_schema if requested.
+ */
+message CommandGetTables {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, all schemas matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+
+  /*
+   * Specifies a filter pattern for tables to search for.
+   * When no table_name_filter_pattern is provided, all tables matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string table_name_filter_pattern = 3;
+
+  // Specifies a filter of table types which must match.

Review comment:
       What is a table type? Is this backend-specific?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r762023341



##########
File path: cpp/src/arrow/flight/sql/CMakeLists.txt
##########
@@ -66,36 +66,34 @@ else()
                                       ${ARROW_TEST_LINK_LIBS})
 endif()
 
-add_arrow_test(flight_sql_test
-               SOURCES
-               client_test.cc
-               server_test.cc
-               example/sqlite_sql_info.cc
-               STATIC_LINK_LIBS
-               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
-               LABELS
-               "arrow_flight_sql")
-
 # Build test server for unit tests
 if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
   find_package(SQLite3Alt REQUIRED)
 
-  add_executable(flight_sql_test_server
-                 test_server_cli.cc
-                 example/sqlite_sql_info.cc
-                 example/sqlite_statement.cc
-                 example/sqlite_statement_batch_reader.cc
-                 example/sqlite_server.cc
-                 example/sqlite_tables_schema_batch_reader.cc)
+  set(flight_sql_test_server_SRCS

Review comment:
       Renamed!
   Now that the sqlite server runs in the same process as the tests on `server_test.cc`, it needs to build the same files as the CLI




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-952157564


   Alright, I got a fully statically linked build and can't reproduce the Protobuf issue, with this diff:
   
   ```diff
   diff --git a/cpp/src/arrow/flight/flight-sql/CMakeLists.txt b/cpp/src/arrow/flight/flight-sql/CMakeLists.txt
   index 7491896fe..f4b6a0546 100644
   --- a/cpp/src/arrow/flight/flight-sql/CMakeLists.txt
   +++ b/cpp/src/arrow/flight/flight-sql/CMakeLists.txt
   @@ -36,7 +36,7 @@ set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENER
    
    add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
    
   -set(ARROW_FLIGHT_SQL_SRCS server.cc)
   +set(ARROW_FLIGHT_SQL_SRCS server.cc "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
    
    add_arrow_lib(arrow_flight_sql
                  CMAKE_PACKAGE_NAME
   @@ -69,8 +69,7 @@ else()
                                          ${ARROW_TEST_LINK_LIBS})
    endif()
    
   -add_executable(flight_sql_test_app test_app_cli.cc
   -                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
   +add_executable(flight_sql_test_app test_app_cli.cc)
    target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
                                                      ${GFLAGS_LIBRARIES})
    
   @@ -78,7 +77,6 @@ add_arrow_test(flight_sql_test
            SOURCES
            client_test.cc
            server_test.cc
   -        "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
            STATIC_LINK_LIBS
            ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
            LABELS
   @@ -95,8 +93,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
              example/sqlite_statement.cc
              example/sqlite_statement_batch_reader.cc
              example/sqlite_server.cc
   -          example/sqlite_tables_schema_batch_reader.cpp
   -          "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
   +          example/sqlite_tables_schema_batch_reader.cpp)
      target_link_libraries(flight_sql_test_server
              PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}
              ${SQLite3_LIBRARIES})
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] JrJuscelino commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
JrJuscelino commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r738764984



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+               STATIC_LINK_LIBS
+               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+               GTest::gtest
+               GTest::gmock
+               LABELS
+               "arrow_flight_sql")
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
+                                                  ${GFLAGS_LIBRARIES})
+
+find_package(SQLite3)
+include_directories(${SQLite3_INCLUDE_DIRS})
+
+add_executable(flight_sql_test_server
+               server.cc
+               test_server_cli.cc
+               example/sqlite_statement.cc
+               example/sqlite_statement_batch_reader.cc
+               example/sqlite_server.cc
+               example/sqlite_tables_schema_batch_reader.cpp
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
+target_link_libraries(flight_sql_test_server
+                      PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}
+                              ${SQLite3_LIBRARIES})

Review comment:
       We just made some changes on CMake, separating the client and server tests, so do you think these changes still applies?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734765778



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       Yes, or really, just link all the FlightSQL sources into libarrow_flight.
   
   Note that the FlightSQL protobuf sources need not be #included like protocol_internal.cc does - that's only done because we need to override things. In this case, they can just be specified in CMake like all the other sources.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734745096



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       You could also have this structure, I think:
   - client.h has an abstract base class and a function `MakePreparedStatement()`
   - client_internal.h has:
   
       ```cpp
       template <class T>
       class PreparedStatementImpl : public PreparedStatement {
       // ...current impl...
       };
       ```
   - In tests, include client_internal.h and instantiate `PreparedStatementImpl<MockClient>`
   - In client.cc, include client_internal.h and instantiate `PreparedStatementImpl<FlightClient>` to implement `MakePreparedStatement`
   
   (maybe a MakePreparedStatementImpl also needs to be templated and in client_internal.h) 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-948761139


   @kylep-dremio 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735819181



##########
File path: cpp/src/arrow/flight/flight-sql/client_impl.h
##########
@@ -0,0 +1,463 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/testing/gtest_util.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/message_lite.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T>
+FlightSqlClientT<T>::FlightSqlClientT(std::unique_ptr<T>& client) {
+  this->client = std::move(client);
+}
+
+template <class T>
+PreparedStatementT<T>::PreparedStatementT(
+    T* client_, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result_,
+    const FlightCallOptions& options_)
+    : client(client_),
+      prepared_statement_result(std::move(prepared_statement_result_)),
+      options(options_) {
+  is_closed = false;
+}
+
+template <class T>
+FlightSqlClientT<T>::~FlightSqlClientT() = default;
+
+template <class T>
+PreparedStatementT<T>::~PreparedStatementT<T>() {
+  Close();
+}
+
+inline FlightDescriptor GetFlightDescriptorForCommand(
+    const google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+template <class T>
+Status GetFlightInfoForCommand(const std::unique_ptr<T>& client,
+                               const FlightCallOptions& options,
+                               std::unique_ptr<FlightInfo>* flight_info,
+                               const google::protobuf::Message& command) {
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  return client->GetFlightInfo(options, descriptor, flight_info);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::Execute(const FlightCallOptions& options,
+                                    const std::string& query,
+                                    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::ExecuteUpdate(const FlightCallOptions& options,
+                                          const std::string& query, int64_t* rows) const {
+  pb::sql::CommandStatementUpdate command;
+  command.set_query(query);
+
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+
+  ARROW_RETURN_NOT_OK(client->DoPut(options, descriptor, NULLPTR, &writer, &reader));
+
+  std::shared_ptr<Buffer> metadata;
+
+  const Status& status = reader->ReadMetadata(&metadata);
+
+  pb::sql::DoPutUpdateResult doPutUpdateResult;
+
+  Buffer* pBuffer = metadata.get();
+
+  const std::string& string = pBuffer->ToString();
+
+  doPutUpdateResult.ParseFrom<google::protobuf::MessageLite::kParse>(string);
+  *rows = doPutUpdateResult.record_count();
+
+  return Status::OK();
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetCatalogs(const FlightCallOptions& options,
+                                        std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetCatalogs command;
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetSchemas(const FlightCallOptions& options,
+                                       const std::string* catalog,
+                                       const std::string* schema_filter_pattern,
+                                       std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetSchemas command;
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+  if (schema_filter_pattern != NULLPTR) {
+    command.set_schema_filter_pattern(*schema_filter_pattern);
+  }
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetTables(const FlightCallOptions& options,
+                                      const std::string* catalog,
+                                      const std::string* schema_filter_pattern,
+                                      const std::string* table_filter_pattern,
+                                      bool include_schema,
+                                      std::vector<std::string>& table_types,
+                                      std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetTables command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema_filter_pattern != NULLPTR) {
+    command.set_schema_filter_pattern(*schema_filter_pattern);
+  }
+
+  if (table_filter_pattern != NULLPTR) {
+    command.set_table_name_filter_pattern(*table_filter_pattern);
+  }
+
+  command.set_include_schema(include_schema);
+
+  for (const std::string& table_type : table_types) {
+    command.add_table_types(table_type);
+  }
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetPrimaryKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table,
+    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetPrimaryKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetExportedKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table,
+    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetExportedKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetImportedKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table,
+    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetImportedKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetCrossReference(
+    const FlightCallOptions& options, const std::string* pk_catalog,
+    const std::string* pk_schema, const std::string& pk_table,
+    const std::string* fk_catalog, const std::string* fk_schema,
+    const std::string& fk_table, std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetCrossReference command;
+
+  if (pk_catalog != NULLPTR) {
+    command.set_pk_catalog(*pk_catalog);
+  }
+  if (pk_schema != NULLPTR) {
+    command.set_pk_schema(*pk_schema);
+  }
+  command.set_pk_table(pk_table);
+
+  if (fk_catalog != NULLPTR) {
+    command.set_fk_catalog(*fk_catalog);
+  }
+  if (fk_schema != NULLPTR) {
+    command.set_fk_schema(*fk_schema);
+  }
+  command.set_fk_table(fk_table);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetTableTypes(
+    const FlightCallOptions& options, std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetTableTypes command;
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::DoGet(const FlightCallOptions& options, const Ticket& ticket,
+                                  std::unique_ptr<FlightStreamReader>* stream) const {
+  return client->DoGet(options, ticket, stream);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::Prepare(
+    const FlightCallOptions& options, const std::string& query,
+    std::shared_ptr<PreparedStatementT<T>>* prepared_statement) {
+  google::protobuf::Any command;
+  pb::sql::ActionCreatePreparedStatementRequest request;
+  request.set_query(query);
+  command.PackFrom(request);
+
+  Action action;
+  action.type = "CreatePreparedStatement";
+  action.body = Buffer::FromString(command.SerializeAsString());
+
+  std::unique_ptr<ResultStream> results;
+
+  ARROW_RETURN_NOT_OK(client->DoAction(options, action, &results));
+
+  std::unique_ptr<Result> result;
+  ARROW_RETURN_NOT_OK(results->Next(&result));
+
+  google::protobuf::Any prepared_result;
+
+  std::shared_ptr<Buffer> message = std::move(result->body);
+
+  prepared_result.ParseFromArray(message->data(), static_cast<int>(message->size()));
+
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+  prepared_result.UnpackTo(&prepared_statement_result);
+
+  prepared_statement->reset(
+      new PreparedStatementT<T>(client.get(), query, prepared_statement_result, options));
+
+  return Status::OK();
+}
+
+template <class T>
+Status PreparedStatementT<T>::Execute(std::unique_ptr<FlightInfo>* info) {
+  if (is_closed) {
+    return Status::Invalid("Statement already closed.");
+  }
+
+  pb::sql::CommandPreparedStatementQuery execute_query_command;
+
+  execute_query_command.set_prepared_statement_handle(
+      prepared_statement_result.prepared_statement_handle());
+
+  google::protobuf::Any any;
+  any.PackFrom(execute_query_command);
+
+  const std::string& string = any.SerializeAsString();
+  const FlightDescriptor descriptor = FlightDescriptor::Command(string);
+
+  if (parameter_binding && parameter_binding->num_rows() > 0) {
+    std::unique_ptr<FlightStreamWriter> writer;
+    std::unique_ptr<FlightMetadataReader> reader;
+    client->DoPut(options, descriptor, parameter_binding->schema(), &writer, &reader);

Review comment:
       Missing RETURN_NOT_OK.

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client = new FlightSqlClient(client);
+  }
+
+  void TearDown() override {
+    server->Stop();
+
+    free(server);
+    free(sql_client);
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(sql_client->Execute({}, "SELECT * FROM intTable", &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  DECLARE_ARRAY(id_array, Int64, ({1, 2, 3}));
+  DECLARE_ARRAY(keyname_array, String, ({"one", "zero", "negative one"}));
+  DECLARE_ARRAY(value_array, Int64, ({1, 0, -1}));
+  DECLARE_ARRAY(foreignId_array, Int64, ({1, 1, 1}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::unique_ptr<FlightInfo> flight_info;
+  std::vector<std::string> table_types;
+  ASSERT_OK(sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types,
+                                  &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  DECLARE_NULL_ARRAY(catalog_name, String, 3);
+  DECLARE_NULL_ARRAY(schema_name, String, 3);
+  DECLARE_ARRAY(table_name, String,
+                ({
+                    "foreignTable",
+                    "intTable",
+                    "sqlite_sequence",
+                }));
+  DECLARE_ARRAY(table_type, String, ({"table", "table", "table"}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  ASSERT_TRUE(expected_table->Equals(*table));

Review comment:
       I'm seeing this fail for me.

##########
File path: cpp/src/arrow/flight/flight-sql/client_impl.h
##########
@@ -0,0 +1,463 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/testing/gtest_util.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/message_lite.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T>
+FlightSqlClientT<T>::FlightSqlClientT(std::unique_ptr<T>& client) {
+  this->client = std::move(client);
+}
+
+template <class T>
+PreparedStatementT<T>::PreparedStatementT(
+    T* client_, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result_,
+    const FlightCallOptions& options_)
+    : client(client_),
+      prepared_statement_result(std::move(prepared_statement_result_)),
+      options(options_) {

Review comment:
       I'm getting -Wreorder here.

##########
File path: cpp/src/arrow/flight/flight-sql/client_impl.h
##########
@@ -0,0 +1,463 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/testing/gtest_util.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/message_lite.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T>
+FlightSqlClientT<T>::FlightSqlClientT(std::unique_ptr<T>& client) {
+  this->client = std::move(client);
+}
+
+template <class T>
+PreparedStatementT<T>::PreparedStatementT(
+    T* client_, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result_,
+    const FlightCallOptions& options_)
+    : client(client_),
+      prepared_statement_result(std::move(prepared_statement_result_)),
+      options(options_) {
+  is_closed = false;
+}
+
+template <class T>
+FlightSqlClientT<T>::~FlightSqlClientT() = default;
+
+template <class T>
+PreparedStatementT<T>::~PreparedStatementT<T>() {
+  Close();

Review comment:
       Missing RETURN_NOT_OK - though we can't do that here. How do we want to deal with this?

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+               STATIC_LINK_LIBS
+               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+               GTest::gtest
+               GTest::gmock
+               LABELS
+               "arrow_flight_sql")
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
+                                                  ${GFLAGS_LIBRARIES})
+
+find_package(SQLite3)
+include_directories(${SQLite3_INCLUDE_DIRS})
+
+add_executable(flight_sql_test_server
+               server.cc
+               test_server_cli.cc
+               example/sqlite_statement.cc
+               example/sqlite_statement_batch_reader.cc
+               example/sqlite_server.cc
+               example/sqlite_tables_schema_batch_reader.cpp
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
+target_link_libraries(flight_sql_test_server
+                      PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}
+                              ${SQLite3_LIBRARIES})

Review comment:
       We need something like `add_dependencies(arrow-flight-sql-test flight_sql_test_app flight_sql_test_server)` so that a partial build of just `arrow-flight-sql-test` works (which speeds up development).

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client = new FlightSqlClient(client);
+  }
+
+  void TearDown() override {
+    server->Stop();
+
+    free(server);
+    free(sql_client);
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(sql_client->Execute({}, "SELECT * FROM intTable", &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  DECLARE_ARRAY(id_array, Int64, ({1, 2, 3}));
+  DECLARE_ARRAY(keyname_array, String, ({"one", "zero", "negative one"}));
+  DECLARE_ARRAY(value_array, Int64, ({1, 0, -1}));
+  DECLARE_ARRAY(foreignId_array, Int64, ({1, 1, 1}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  ASSERT_TRUE(expected_table->Equals(*table));

Review comment:
       We should use AssertTablesEqual which also shows the diff (with verbose=true).

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+               STATIC_LINK_LIBS
+               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+               GTest::gtest
+               GTest::gmock
+               LABELS
+               "arrow_flight_sql")
+
+add_executable(flight_sql_test_app test_app_cli.cc

Review comment:
       We also need to guard these definitions because flight_sql_test_app uses Googletest.

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client = new FlightSqlClient(client);
+  }
+
+  void TearDown() override {
+    server->Stop();
+
+    free(server);
+    free(sql_client);
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(sql_client->Execute({}, "SELECT * FROM intTable", &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  DECLARE_ARRAY(id_array, Int64, ({1, 2, 3}));
+  DECLARE_ARRAY(keyname_array, String, ({"one", "zero", "negative one"}));
+  DECLARE_ARRAY(value_array, Int64, ({1, 0, -1}));
+  DECLARE_ARRAY(foreignId_array, Int64, ({1, 1, 1}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::unique_ptr<FlightInfo> flight_info;
+  std::vector<std::string> table_types;
+  ASSERT_OK(sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types,
+                                  &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  DECLARE_NULL_ARRAY(catalog_name, String, 3);
+  DECLARE_NULL_ARRAY(schema_name, String, 3);
+  DECLARE_ARRAY(table_name, String,
+                ({
+                    "foreignTable",
+                    "intTable",
+                    "sqlite_sequence",
+                }));
+  DECLARE_ARRAY(table_type, String, ({"table", "table", "table"}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableFilter) {
+  std::unique_ptr<FlightInfo> flight_info;
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK(sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern, false,
+                                  table_types, &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  DECLARE_NULL_ARRAY(catalog_name, String, 1);
+  DECLARE_NULL_ARRAY(schema_name, String, 1);
+  DECLARE_ARRAY(table_name, String, ({"intTable"}));
+  DECLARE_ARRAY(table_type, String, ({"table"}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableTypesFilter) {
+  std::unique_ptr<FlightInfo> flight_info;
+  std::vector<std::string> table_types{"index"};
+
+  ASSERT_OK(sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types,
+                                  &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_TRUE(table->schema()->Equals(SqlSchema::GetTablesSchema()));
+
+  ASSERT_EQ(table->num_rows(), 0);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithUnexistenceTableTypeFilter) {
+  std::unique_ptr<FlightInfo> flight_info;
+  std::vector<std::string> table_types{"table"};
+
+  ASSERT_OK(sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types,
+                                  &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  DECLARE_NULL_ARRAY(catalog_name, String, 3);
+  DECLARE_NULL_ARRAY(schema_name, String, 3);
+  DECLARE_ARRAY(table_name, String,
+                ({
+                    "foreignTable",
+                    "intTable",
+                    "sqlite_sequence",
+                }));
+  DECLARE_ARRAY(table_type, String, ({"table", "table", "table"}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithIncludedSchemas) {
+  std::unique_ptr<FlightInfo> flight_info;
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK(sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern, true,
+                                  table_types, &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  DECLARE_NULL_ARRAY(catalog_name, String, 1);
+  DECLARE_NULL_ARRAY(schema_name, String, 1);
+  DECLARE_ARRAY(table_name, String, ({"intTable"}));
+  DECLARE_ARRAY(table_type, String, ({"table"}));
+
+  const std::shared_ptr<Schema> schema_table =
+      arrow::schema({arrow::field("id", int64(), true, NULL),
+                     arrow::field("keyName", utf8(), true, NULL),
+                     arrow::field("value", int64(), true, NULL),
+                     arrow::field("foreignId", int64(), true, NULL)});
+
+  const arrow::Result<std::shared_ptr<Buffer>>& value =
+      ipc::SerializeSchema(*schema_table);
+  value.ValueOrDie()->data(), value.ValueOrDie()->size();
+
+  DECLARE_BINARY_ARRAY(table_schema, ({value.ValueOrDie()->data()}),
+                       value.ValueOrDie()->size());
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetTablesSchemaWithIncludedSchema(),
+                  {catalog_name, schema_name, table_name, table_type, table_schema});
+
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandGetCatalogs) {
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(sql_client->GetCatalogs({}, &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema = SqlSchema::GetCatalogsSchema();
+
+  ASSERT_TRUE(table->schema()->Equals(*expected_schema));
+  ASSERT_EQ(0, table->num_rows());
+}
+
+TEST(TestFlightSqlServer, TestCommandGetSchemas) {
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(sql_client->GetSchemas({}, NULLPTR, NULLPTR, &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema = SqlSchema::GetSchemasSchema();
+
+  ASSERT_TRUE(table->schema()->Equals(*expected_schema));
+  ASSERT_EQ(0, table->num_rows());
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTableTypes) {
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(sql_client->GetTableTypes({}, &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  DECLARE_ARRAY(table_type, String, ({"table"}));
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetTableTypesSchema(), {table_type});
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandStatementUpdate) {
+  int64_t result;
+  ASSERT_OK(sql_client->ExecuteUpdate(
+      {},
+      "INSERT INTO intTable (keyName, value) VALUES "
+      "('KEYNAME1', 1001), ('KEYNAME2', 1002), ('KEYNAME3', 1003)",
+      &result));
+  ASSERT_EQ(3, result);
+
+  ASSERT_OK(
+      sql_client->ExecuteUpdate({},
+                                "UPDATE intTable SET keyName = 'KEYNAME1' "
+                                "WHERE keyName = 'KEYNAME2' OR keyName = 'KEYNAME3'",
+                                &result));
+  ASSERT_EQ(2, result);
+
+  ASSERT_OK(sql_client->ExecuteUpdate(
+      {}, "DELETE FROM intTable WHERE keyName = 'KEYNAME1'", &result));
+  ASSERT_EQ(3, result);
+}
+
+TEST(TestFlightSqlServer, TestCommandPreparedStatementQuery) {
+  std::shared_ptr<PreparedStatement> prepared_statement;
+  ASSERT_OK(sql_client->Prepare({}, "SELECT * FROM intTable", &prepared_statement));
+
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(prepared_statement->Execute(&flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  DECLARE_ARRAY(id_array, Int64, ({1, 2, 3}));
+  DECLARE_ARRAY(keyname_array, String, ({"one", "zero", "negative one"}));
+  DECLARE_ARRAY(value_array, Int64, ({1, 0, -1}));
+  DECLARE_ARRAY(foreignId_array, Int64, ({1, 1, 1}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandPreparedStatementQueryWithParameterBinding) {
+  std::shared_ptr<PreparedStatement> prepared_statement;
+  ASSERT_OK(sql_client->Prepare({}, "SELECT * FROM intTable WHERE keyName LIKE ?",
+                                &prepared_statement));
+
+  std::shared_ptr<Schema> parameter_schema;
+  ASSERT_OK(prepared_statement->GetParameterSchema(&parameter_schema));
+
+  const std::shared_ptr<Schema>& expected_parameter_schema =
+      arrow::schema({arrow::field("parameter_1", example::GetUnknownColumnDataType())});
+
+  ASSERT_TRUE(expected_parameter_schema->Equals(*parameter_schema));
+
+  std::shared_ptr<Array> type_ids;
+  ArrayFromVector<Int8Type>({0}, &type_ids);
+  std::shared_ptr<Array> offsets;
+  ArrayFromVector<Int32Type>({0}, &offsets);
+
+  std::shared_ptr<Array> string_array;
+  ArrayFromVector<StringType, std::string>({"%one"}, &string_array);
+  std::shared_ptr<Array> bytes_array;
+  ArrayFromVector<BinaryType, std::string>({}, &bytes_array);
+  std::shared_ptr<Array> bigint_array;
+  ArrayFromVector<Int64Type>({}, &bigint_array);
+  std::shared_ptr<Array> double_array;
+  ArrayFromVector<FloatType>({}, &double_array);
+
+  ASSERT_OK_AND_ASSIGN(
+      auto parameter_1_array,
+      DenseUnionArray::Make(*type_ids, *offsets,
+                            {string_array, bytes_array, bigint_array, double_array},
+                            {"string", "bytes", "bigint", "double"}, {0, 1, 2, 3}));
+
+  const std::shared_ptr<RecordBatch>& record_batch =
+      RecordBatch::Make(parameter_schema, 1, {parameter_1_array});
+
+  ASSERT_OK(prepared_statement->SetParameters(record_batch));
+
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(prepared_statement->Execute(&flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  DECLARE_ARRAY(id_array, Int64, ({1, 3}));
+  DECLARE_ARRAY(keyname_array, String, ({"one", "negative one"}));
+  DECLARE_ARRAY(value_array, Int64, ({1, -1}));
+  DECLARE_ARRAY(foreignId_array, Int64, ({1, 1}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  ASSERT_TRUE(expected_table->Equals(*table));

Review comment:
       I'm seeing this fail for me.

##########
File path: cpp/src/arrow/flight/flight-sql/client_impl.h
##########
@@ -0,0 +1,463 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/testing/gtest_util.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/message_lite.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T>
+FlightSqlClientT<T>::FlightSqlClientT(std::unique_ptr<T>& client) {
+  this->client = std::move(client);
+}
+
+template <class T>
+PreparedStatementT<T>::PreparedStatementT(
+    T* client_, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result_,
+    const FlightCallOptions& options_)
+    : client(client_),
+      prepared_statement_result(std::move(prepared_statement_result_)),
+      options(options_) {
+  is_closed = false;
+}
+
+template <class T>
+FlightSqlClientT<T>::~FlightSqlClientT() = default;
+
+template <class T>
+PreparedStatementT<T>::~PreparedStatementT<T>() {
+  Close();
+}
+
+inline FlightDescriptor GetFlightDescriptorForCommand(
+    const google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+template <class T>
+Status GetFlightInfoForCommand(const std::unique_ptr<T>& client,
+                               const FlightCallOptions& options,
+                               std::unique_ptr<FlightInfo>* flight_info,
+                               const google::protobuf::Message& command) {
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  return client->GetFlightInfo(options, descriptor, flight_info);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::Execute(const FlightCallOptions& options,
+                                    const std::string& query,
+                                    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::ExecuteUpdate(const FlightCallOptions& options,
+                                          const std::string& query, int64_t* rows) const {
+  pb::sql::CommandStatementUpdate command;
+  command.set_query(query);
+
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+
+  ARROW_RETURN_NOT_OK(client->DoPut(options, descriptor, NULLPTR, &writer, &reader));
+
+  std::shared_ptr<Buffer> metadata;
+
+  const Status& status = reader->ReadMetadata(&metadata);

Review comment:
       Status is ignored here - should be RETURN_NOT_OK.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742287999



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       The intent is that the library build and unit test build compile and link client.cc and client_test.cc respectively. These two files shouldn't be passed to the same linker run at once.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r738781330



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,116 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")

Review comment:
       nit: just to point this out again, I think we should stick with underscores in directory names to be consistent.

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,116 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc client_internal.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}

Review comment:
       This variable doesn't appear to ever be set - is it needed?

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+using StatementQuery = struct StatementQuery { std::string query; };
+
+using StatementUpdate = struct StatementUpdate { std::string query; };
+
+using StatementQueryTicket = struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+using PreparedStatementQuery = struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+using PreparedStatementUpdate = struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+using GetSqlInfo = struct GetSqlInfo {
+  // TODO: To be implemented.
+};
+
+using GetSchemas = struct GetSchemas {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema_filter_pattern;
+  std::string schema_filter_pattern;
+};
+
+using GetTables = struct GetTables {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema_filter_pattern;
+  std::string schema_filter_pattern;
+  bool has_table_name_filter_pattern;
+  std::string table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+using GetPrimaryKeys = struct GetPrimaryKeys {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema;
+  std::string schema;
+  std::string table;
+};
+
+using GetExportedKeys = struct GetExportedKeys {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema;
+  std::string schema;
+  std::string table;
+};
+
+using GetImportedKeys = struct GetImportedKeys {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema;
+  std::string schema;
+  std::string table;
+};
+
+using GetCrossReference = struct GetCrossReference {
+  bool has_pk_catalog;
+  std::string pk_catalog;
+  bool has_pk_schema;
+  std::string pk_schema;
+  std::string pk_table;
+  bool has_fk_catalog;
+  std::string fk_catalog;
+  bool has_fk_schema;
+  std::string fk_schema;
+  std::string fk_table;
+};
+
+using ActionCreatePreparedStatementRequest = struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+using ActionClosePreparedStatementRequest = struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+using ActionCreatePreparedStatementResult = struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+class FlightSqlServerBase : public FlightServerBase {

Review comment:
       ```suggestion
   class ARROW_EXPORT FlightSqlServerBase : public FlightServerBase {
   ```

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>

Review comment:
       Ditto for boost.

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client = new FlightSqlClient(client);
+  }
+
+  void TearDown() override {
+    server->Stop();
+
+    free(server);
+    free(sql_client);

Review comment:
       Ah sorry if it wasn't clear - we need to do delete or use unique_ptr, since AddressSanitizer-enabled builds will fail here since we're pairing new and free.

##########
File path: cpp/src/arrow/flight/flight-sql/client.cc
##########
@@ -0,0 +1,442 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/client.h>
+#include <arrow/flight/flight-sql/client_internal.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/result.h>
+#include <arrow/testing/gtest_util.h>
+#include <arrow/util/logging.h>
+#include <google/protobuf/any.pb.h>
+
+#include <memory>
+#include <utility>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+FlightSqlClient::FlightSqlClient(std::shared_ptr<internal::FlightClientImpl> client)
+    : impl_(std::move(client)) {}
+
+FlightSqlClient::FlightSqlClient(std::unique_ptr<FlightClient> client)
+    : impl_(internal::FlightClientImpl_Create(std::move(client))) {}
+
+FlightSqlClient::PreparedStatement::PreparedStatement(
+    std::shared_ptr<internal::FlightClientImpl> client, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+    FlightCallOptions options)
+    : client_(client),
+      options_(std::move(options)),
+      prepared_statement_result_(std::move(prepared_statement_result)),
+      is_closed_(false) {}
+
+FlightSqlClient::~FlightSqlClient() = default;
+
+FlightSqlClient::PreparedStatement::~PreparedStatement() {
+  const Status status = Close();
+  if (!status.ok()) {
+    ARROW_LOG(ERROR) << "Failed to delete PreparedStatement: " << status.ToString();
+  }
+}
+
+inline FlightDescriptor GetFlightDescriptorForCommand(
+    const google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> GetFlightInfoForCommand(
+    internal::FlightClientImpl& client, const FlightCallOptions& options,
+    const google::protobuf::Message& command) {
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  std::unique_ptr<FlightInfo> flight_info;
+  ARROW_RETURN_NOT_OK(internal::FlightClientImpl_GetFlightInfo(client, options,
+                                                               descriptor, &flight_info));
+
+  return std::move(flight_info);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::Execute(
+    const FlightCallOptions& options, const std::string& query) const {
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<int64_t> FlightSqlClient::ExecuteUpdate(const FlightCallOptions& options,
+                                                      const std::string& query) const {
+  pb::sql::CommandStatementUpdate command;
+  command.set_query(query);
+
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+
+  ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoPut(*impl_, options, descriptor,
+                                                       NULLPTR, &writer, &reader));
+
+  std::shared_ptr<Buffer> metadata;
+
+  ARROW_RETURN_NOT_OK(reader->ReadMetadata(&metadata));
+
+  pb::sql::DoPutUpdateResult doPutUpdateResult;
+
+  pb::sql::DoPutUpdateResult result;
+  if (!result.ParseFromArray(metadata->data(), static_cast<int>(metadata->size()))) {
+    return Status::Invalid("Unable to parse DoPutUpdateResult object.");
+  }
+
+  return result.record_count();
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetCatalogs(
+    const FlightCallOptions& options) const {
+  pb::sql::CommandGetCatalogs command;
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetSchemas(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema_filter_pattern) const {
+  pb::sql::CommandGetSchemas command;
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+  if (schema_filter_pattern != NULLPTR) {
+    command.set_schema_filter_pattern(*schema_filter_pattern);
+  }
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetTables(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+    bool include_schema, std::vector<std::string>& table_types) const {
+  pb::sql::CommandGetTables command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema_filter_pattern != NULLPTR) {
+    command.set_schema_filter_pattern(*schema_filter_pattern);
+  }
+
+  if (table_filter_pattern != NULLPTR) {
+    command.set_table_name_filter_pattern(*table_filter_pattern);
+  }
+
+  command.set_include_schema(include_schema);
+
+  for (const std::string& table_type : table_types) {
+    command.add_table_types(table_type);
+  }
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetPrimaryKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table) const {
+  pb::sql::CommandGetPrimaryKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetExportedKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table) const {
+  pb::sql::CommandGetExportedKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetImportedKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table) const {
+  pb::sql::CommandGetImportedKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetCrossReference(
+    const FlightCallOptions& options, const std::string* pk_catalog,
+    const std::string* pk_schema, const std::string& pk_table,
+    const std::string* fk_catalog, const std::string* fk_schema,
+    const std::string& fk_table) const {
+  pb::sql::CommandGetCrossReference command;
+
+  if (pk_catalog != NULLPTR) {
+    command.set_pk_catalog(*pk_catalog);
+  }
+  if (pk_schema != NULLPTR) {
+    command.set_pk_schema(*pk_schema);
+  }
+  command.set_pk_table(pk_table);
+
+  if (fk_catalog != NULLPTR) {
+    command.set_fk_catalog(*fk_catalog);
+  }
+  if (fk_schema != NULLPTR) {
+    command.set_fk_schema(*fk_schema);
+  }
+  command.set_fk_table(fk_table);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetTableTypes(
+    const FlightCallOptions& options) const {
+  pb::sql::CommandGetTableTypes command;
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightStreamReader>> FlightSqlClient::DoGet(
+    const FlightCallOptions& options, const Ticket& ticket) const {
+  std::unique_ptr<FlightStreamReader> stream;
+  ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoGet(*impl_, options, ticket, &stream));
+
+  return std::move(stream);
+}
+
+arrow::Result<std::shared_ptr<FlightSqlClient::PreparedStatement>>
+FlightSqlClient::Prepare(const FlightCallOptions& options, const std::string& query) {
+  google::protobuf::Any command;
+  pb::sql::ActionCreatePreparedStatementRequest request;
+  request.set_query(query);
+  command.PackFrom(request);
+
+  Action action;
+  action.type = "CreatePreparedStatement";
+  action.body = Buffer::FromString(command.SerializeAsString());
+
+  std::unique_ptr<ResultStream> results;
+
+  ARROW_RETURN_NOT_OK(
+      internal::FlightClientImpl_DoAction(*impl_, options, action, &results));
+
+  std::unique_ptr<Result> result;
+  ARROW_RETURN_NOT_OK(results->Next(&result));
+
+  google::protobuf::Any prepared_result;
+
+  std::shared_ptr<Buffer> message = std::move(result->body);
+  if (!prepared_result.ParseFromArray(message->data(),
+                                      static_cast<int>(message->size()))) {
+    return Status::Invalid("Unable to parse packed ActionCreatePreparedStatementResult");
+  }
+
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+  if (!prepared_result.UnpackTo(&prepared_statement_result)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementResult");
+  }
+
+  return std::make_shared<PreparedStatement>(impl_, query, prepared_statement_result,
+                                             options);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::PreparedStatement::Execute() {
+  if (is_closed_) {
+    return Status::Invalid("Statement already closed.");
+  }
+
+  pb::sql::CommandPreparedStatementQuery execute_query_command;
+
+  execute_query_command.set_prepared_statement_handle(
+      prepared_statement_result_.prepared_statement_handle());
+
+  google::protobuf::Any any;
+  any.PackFrom(execute_query_command);
+
+  const std::string& string = any.SerializeAsString();
+  const FlightDescriptor descriptor = FlightDescriptor::Command(string);
+
+  if (parameter_binding_ && parameter_binding_->num_rows() > 0) {
+    std::unique_ptr<FlightStreamWriter> writer;
+    std::unique_ptr<FlightMetadataReader> reader;
+    ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoPut(
+        *client_, options_, descriptor, parameter_binding_->schema(), &writer, &reader));
+
+    ARROW_RETURN_NOT_OK(writer->WriteRecordBatch(*parameter_binding_));
+    ARROW_RETURN_NOT_OK(writer->DoneWriting());
+    // Wait for the server to ack the result
+    std::shared_ptr<Buffer> buffer;
+    ARROW_RETURN_NOT_OK(reader->ReadMetadata(&buffer));
+  }
+
+  std::unique_ptr<FlightInfo> info;
+  ARROW_RETURN_NOT_OK(
+      internal::FlightClientImpl_GetFlightInfo(*client_, options_, descriptor, &info));
+
+  return std::move(info);
+}
+
+arrow::Result<int64_t> FlightSqlClient::PreparedStatement::ExecuteUpdate() {
+  if (is_closed_) {
+    return Status::Invalid("Statement already closed.");
+  }
+
+  pb::sql::CommandPreparedStatementUpdate command;
+  command.set_prepared_statement_handle(
+      prepared_statement_result_.prepared_statement_handle());
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+
+  if (parameter_binding_ && parameter_binding_->num_rows() > 0) {
+    ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoPut(
+        *client_, options_, descriptor, parameter_binding_->schema(), &writer, &reader));
+    ARROW_RETURN_NOT_OK(writer->WriteRecordBatch(*parameter_binding_));
+  } else {
+    const std::shared_ptr<Schema> schema = arrow::schema({});
+    ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoPut(*client_, options_, descriptor,
+                                                         schema, &writer, &reader));
+    const auto& record_batch =
+        arrow::RecordBatch::Make(schema, 0, (std::vector<std::shared_ptr<Array>>){});
+    ARROW_RETURN_NOT_OK(writer->WriteRecordBatch(*record_batch));
+  }
+
+  ARROW_RETURN_NOT_OK(writer->DoneWriting());
+  std::shared_ptr<Buffer> metadata;
+  ARROW_RETURN_NOT_OK(reader->ReadMetadata(&metadata));
+  ARROW_RETURN_NOT_OK(writer->Close());
+
+  pb::sql::DoPutUpdateResult result;
+  if (!result.ParseFromArray(metadata->data(), static_cast<int>(metadata->size()))) {
+    return Status::Invalid("Unable to parse DoPutUpdateResult object.");
+  }
+
+  return result.record_count();
+}
+
+Status FlightSqlClient::PreparedStatement::SetParameters(
+    std::shared_ptr<RecordBatch> parameter_binding) {
+  parameter_binding_ = std::move(parameter_binding);
+
+  return Status::OK();
+}
+
+bool FlightSqlClient::PreparedStatement::IsClosed() const { return is_closed_; }
+
+arrow::Result<std::shared_ptr<Schema>>
+FlightSqlClient::PreparedStatement::GetResultSetSchema() {

Review comment:
       Also if we do the parsing in `Prepare` I think we can get rid of having to pass the Protobuf to the constructor here, which obviates the comment about not exposing the Protobuf types in the public header.

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+using StatementQuery = struct StatementQuery { std::string query; };

Review comment:
       why the `using` here? It should all be able to be `struct StatmentQuery {...};`.

##########
File path: cpp/src/arrow/flight/flight-sql/server.cc
##########
@@ -0,0 +1,672 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/flight-sql/server.h"
+
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <google/protobuf/any.pb.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <sstream>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+
+std::string arrow::flight::sql::FlightSqlServerBase::CreateStatementQueryTicket(

Review comment:
       Why not move this into the `namespace` declarations?

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+#include "arrow/api.h"

Review comment:
       nit: try not to include "arrow/api.h" in a public header as it can slow compilation significantly - either include the headers needed, using `type_fwd.h` where possible, or forward-declare things as needed.

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>

Review comment:
       Did we mean to depend on sqlite3.h here?

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+using StatementQuery = struct StatementQuery { std::string query; };
+
+using StatementUpdate = struct StatementUpdate { std::string query; };
+
+using StatementQueryTicket = struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+using PreparedStatementQuery = struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+using PreparedStatementUpdate = struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+using GetSqlInfo = struct GetSqlInfo {
+  // TODO: To be implemented.
+};
+
+using GetSchemas = struct GetSchemas {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema_filter_pattern;
+  std::string schema_filter_pattern;
+};
+
+using GetTables = struct GetTables {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema_filter_pattern;
+  std::string schema_filter_pattern;
+  bool has_table_name_filter_pattern;
+  std::string table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+using GetPrimaryKeys = struct GetPrimaryKeys {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema;
+  std::string schema;
+  std::string table;
+};
+
+using GetExportedKeys = struct GetExportedKeys {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema;
+  std::string schema;
+  std::string table;
+};
+
+using GetImportedKeys = struct GetImportedKeys {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema;
+  std::string schema;
+  std::string table;
+};
+
+using GetCrossReference = struct GetCrossReference {
+  bool has_pk_catalog;
+  std::string pk_catalog;
+  bool has_pk_schema;
+  std::string pk_schema;
+  std::string pk_table;
+  bool has_fk_catalog;
+  std::string fk_catalog;
+  bool has_fk_schema;
+  std::string fk_schema;
+  std::string fk_table;
+};
+
+using ActionCreatePreparedStatementRequest = struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+using ActionClosePreparedStatementRequest = struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+using ActionCreatePreparedStatementResult = struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+class FlightSqlServerBase : public FlightServerBase {
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType FLIGHT_SQL_CREATE_PREPARED_STATEMENT =

Review comment:
       nit: the naming convention for constants in this codebase should be `kFlightSqlCreatePreparedStatement`. But since we're in FlightSQL already I would probably name this something like `kCreatePreparedStatementActionType`.

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,233 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl;
+}
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+ private:
+  std::shared_ptr<internal::FlightClientImpl> impl_;
+
+ public:
+  class PreparedStatement;
+
+  explicit FlightSqlClient(std::shared_ptr<internal::FlightClientImpl> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket) const;
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types) const;
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table) const;
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options) const;
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(
+      const FlightCallOptions& options, const std::vector<int>& sql_info) const;
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(
+      const FlightCallOptions& options,
+      const std::vector<pb::sql::SqlInfo>& sql_info) const;
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  explicit FlightSqlClient(std::unique_ptr<FlightClient> client);
+
+  class PreparedStatement {

Review comment:
       Maybe un-nest this class from FlightSqlClient?

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+#include "arrow/api.h"

Review comment:
       It seems you should need only `arrow/status.h` from a quick glance.

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+using StatementQuery = struct StatementQuery { std::string query; };
+
+using StatementUpdate = struct StatementUpdate { std::string query; };
+
+using StatementQueryTicket = struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+using PreparedStatementQuery = struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+using PreparedStatementUpdate = struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+using GetSqlInfo = struct GetSqlInfo {
+  // TODO: To be implemented.
+};
+
+using GetSchemas = struct GetSchemas {
+  bool has_catalog;
+  std::string catalog;

Review comment:
       We can include `arrow/util/optional.h` and use `util::optional<std::string>` to clean this up.

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,233 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl;
+}
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+ private:
+  std::shared_ptr<internal::FlightClientImpl> impl_;
+
+ public:
+  class PreparedStatement;
+
+  explicit FlightSqlClient(std::shared_ptr<internal::FlightClientImpl> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket) const;
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types) const;
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table) const;
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options) const;
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(
+      const FlightCallOptions& options, const std::vector<int>& sql_info) const;
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(
+      const FlightCallOptions& options,
+      const std::vector<pb::sql::SqlInfo>& sql_info) const;
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  explicit FlightSqlClient(std::unique_ptr<FlightClient> client);
+
+  class PreparedStatement {
+    std::shared_ptr<internal::FlightClientImpl> client_;
+    FlightCallOptions options_;
+    pb::sql::ActionCreatePreparedStatementResult prepared_statement_result_;
+    std::shared_ptr<RecordBatch> parameter_binding_;
+    bool is_closed_;
+
+   public:
+    /// \brief Constructor for the PreparedStatement class.
+    /// \param[in] query      The query that will be executed.
+    PreparedStatement(
+        std::shared_ptr<internal::FlightClientImpl> client_, const std::string& query,
+        pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+        FlightCallOptions options);
+
+    /// \brief Default destructor for the PreparedStatement class.
+    /// The destructor will call the Close method from the class in order,
+    /// to send a request to close the PreparedStatement.
+    ~PreparedStatement();

Review comment:
       I think we should note that it's best to explicitly close the statement or else errors can't be caught.

##########
File path: cpp/src/arrow/flight/flight-sql/server.cc
##########
@@ -0,0 +1,672 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/flight-sql/server.h"
+
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <google/protobuf/any.pb.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <sstream>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+
+std::string arrow::flight::sql::FlightSqlServerBase::CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  const std::string& ticket_string = ticket.SerializeAsString();
+  return ticket_string;
+}
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.has_pk_catalog = command.has_pk_catalog();
+  result.pk_catalog = command.pk_catalog();
+  result.has_pk_schema = command.has_pk_schema();
+  result.pk_schema = command.pk_schema();
+  result.pk_table = command.pk_table();
+  result.has_fk_catalog = command.has_fk_catalog();
+  result.fk_catalog = command.fk_catalog();
+  result.has_fk_schema = command.has_fk_schema();
+  result.fk_schema = command.fk_schema();
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.has_catalog = command.has_catalog();
+  result.catalog = command.catalog();
+  result.has_schema = command.has_schema();
+  result.schema = command.schema();
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.has_catalog = command.has_catalog();
+  result.catalog = command.catalog();
+  result.has_schema = command.has_schema();
+  result.schema = command.schema();
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.has_catalog = command.has_catalog();
+  result.catalog = command.catalog();
+  result.has_schema = command.has_schema();
+  result.schema = command.schema();
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.has_catalog = command.has_catalog();
+  result.catalog = command.catalog();
+  result.has_schema_filter_pattern = command.has_schema_filter_pattern();
+  result.schema_filter_pattern = command.schema_filter_pattern();
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types;
+  table_types.reserve(command.table_types_size());
+  for (const auto& item : command.table_types()) {
+    table_types.push_back(item);
+  }
+  GetTables result;
+  result.has_catalog = command.has_catalog();
+  result.catalog = command.catalog();
+  result.has_schema_filter_pattern = command.has_schema_filter_pattern();
+  result.schema_filter_pattern = command.schema_filter_pattern();
+  result.has_table_name_filter_pattern = command.has_table_name_filter_pattern();
+  result.table_name_filter_pattern = command.table_name_filter_pattern();
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(internal_command, context, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(internal_command, context, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(internal_command, context, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(command, context, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command, ParseCommandGetSqlInfo(any));
+    return GetFlightInfoSqlInfo(internal_command, context, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(internal_command, context, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(internal_command, context, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(internal_command, context, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(internal_command, context, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(command, context, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(internal_command, context, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(internal_command, context, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(command, context, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command, ParseCommandGetSqlInfo(any));
+    return DoGetSqlInfo(internal_command, context, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(internal_command, context, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(internal_command, context, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(internal_command, context, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(internal_command, context, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()));

Review comment:
       Check the return value here?

##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));

Review comment:
       ^still wondering about this.

##########
File path: cpp/src/arrow/flight/flight-sql/client.cc
##########
@@ -0,0 +1,442 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/client.h>
+#include <arrow/flight/flight-sql/client_internal.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/result.h>
+#include <arrow/testing/gtest_util.h>
+#include <arrow/util/logging.h>
+#include <google/protobuf/any.pb.h>
+
+#include <memory>
+#include <utility>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+FlightSqlClient::FlightSqlClient(std::shared_ptr<internal::FlightClientImpl> client)
+    : impl_(std::move(client)) {}
+
+FlightSqlClient::FlightSqlClient(std::unique_ptr<FlightClient> client)
+    : impl_(internal::FlightClientImpl_Create(std::move(client))) {}
+
+FlightSqlClient::PreparedStatement::PreparedStatement(
+    std::shared_ptr<internal::FlightClientImpl> client, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+    FlightCallOptions options)
+    : client_(client),
+      options_(std::move(options)),
+      prepared_statement_result_(std::move(prepared_statement_result)),
+      is_closed_(false) {}
+
+FlightSqlClient::~FlightSqlClient() = default;
+
+FlightSqlClient::PreparedStatement::~PreparedStatement() {
+  const Status status = Close();
+  if (!status.ok()) {
+    ARROW_LOG(ERROR) << "Failed to delete PreparedStatement: " << status.ToString();
+  }
+}
+
+inline FlightDescriptor GetFlightDescriptorForCommand(
+    const google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> GetFlightInfoForCommand(
+    internal::FlightClientImpl& client, const FlightCallOptions& options,
+    const google::protobuf::Message& command) {
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  std::unique_ptr<FlightInfo> flight_info;
+  ARROW_RETURN_NOT_OK(internal::FlightClientImpl_GetFlightInfo(client, options,
+                                                               descriptor, &flight_info));
+
+  return std::move(flight_info);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::Execute(
+    const FlightCallOptions& options, const std::string& query) const {
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<int64_t> FlightSqlClient::ExecuteUpdate(const FlightCallOptions& options,
+                                                      const std::string& query) const {
+  pb::sql::CommandStatementUpdate command;
+  command.set_query(query);
+
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+
+  ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoPut(*impl_, options, descriptor,
+                                                       NULLPTR, &writer, &reader));
+
+  std::shared_ptr<Buffer> metadata;
+
+  ARROW_RETURN_NOT_OK(reader->ReadMetadata(&metadata));
+
+  pb::sql::DoPutUpdateResult doPutUpdateResult;
+
+  pb::sql::DoPutUpdateResult result;
+  if (!result.ParseFromArray(metadata->data(), static_cast<int>(metadata->size()))) {
+    return Status::Invalid("Unable to parse DoPutUpdateResult object.");
+  }
+
+  return result.record_count();
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetCatalogs(
+    const FlightCallOptions& options) const {
+  pb::sql::CommandGetCatalogs command;
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetSchemas(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema_filter_pattern) const {
+  pb::sql::CommandGetSchemas command;
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+  if (schema_filter_pattern != NULLPTR) {
+    command.set_schema_filter_pattern(*schema_filter_pattern);
+  }
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetTables(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+    bool include_schema, std::vector<std::string>& table_types) const {
+  pb::sql::CommandGetTables command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema_filter_pattern != NULLPTR) {
+    command.set_schema_filter_pattern(*schema_filter_pattern);
+  }
+
+  if (table_filter_pattern != NULLPTR) {
+    command.set_table_name_filter_pattern(*table_filter_pattern);
+  }
+
+  command.set_include_schema(include_schema);
+
+  for (const std::string& table_type : table_types) {
+    command.add_table_types(table_type);
+  }
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetPrimaryKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table) const {
+  pb::sql::CommandGetPrimaryKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetExportedKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table) const {
+  pb::sql::CommandGetExportedKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetImportedKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table) const {
+  pb::sql::CommandGetImportedKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetCrossReference(
+    const FlightCallOptions& options, const std::string* pk_catalog,
+    const std::string* pk_schema, const std::string& pk_table,
+    const std::string* fk_catalog, const std::string* fk_schema,
+    const std::string& fk_table) const {
+  pb::sql::CommandGetCrossReference command;
+
+  if (pk_catalog != NULLPTR) {
+    command.set_pk_catalog(*pk_catalog);
+  }
+  if (pk_schema != NULLPTR) {
+    command.set_pk_schema(*pk_schema);
+  }
+  command.set_pk_table(pk_table);
+
+  if (fk_catalog != NULLPTR) {
+    command.set_fk_catalog(*fk_catalog);
+  }
+  if (fk_schema != NULLPTR) {
+    command.set_fk_schema(*fk_schema);
+  }
+  command.set_fk_table(fk_table);
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::GetTableTypes(
+    const FlightCallOptions& options) const {
+  pb::sql::CommandGetTableTypes command;
+
+  return GetFlightInfoForCommand(*impl_, options, command);
+}
+
+arrow::Result<std::unique_ptr<FlightStreamReader>> FlightSqlClient::DoGet(
+    const FlightCallOptions& options, const Ticket& ticket) const {
+  std::unique_ptr<FlightStreamReader> stream;
+  ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoGet(*impl_, options, ticket, &stream));
+
+  return std::move(stream);
+}
+
+arrow::Result<std::shared_ptr<FlightSqlClient::PreparedStatement>>
+FlightSqlClient::Prepare(const FlightCallOptions& options, const std::string& query) {
+  google::protobuf::Any command;
+  pb::sql::ActionCreatePreparedStatementRequest request;
+  request.set_query(query);
+  command.PackFrom(request);
+
+  Action action;
+  action.type = "CreatePreparedStatement";
+  action.body = Buffer::FromString(command.SerializeAsString());
+
+  std::unique_ptr<ResultStream> results;
+
+  ARROW_RETURN_NOT_OK(
+      internal::FlightClientImpl_DoAction(*impl_, options, action, &results));
+
+  std::unique_ptr<Result> result;
+  ARROW_RETURN_NOT_OK(results->Next(&result));
+
+  google::protobuf::Any prepared_result;
+
+  std::shared_ptr<Buffer> message = std::move(result->body);
+  if (!prepared_result.ParseFromArray(message->data(),
+                                      static_cast<int>(message->size()))) {
+    return Status::Invalid("Unable to parse packed ActionCreatePreparedStatementResult");
+  }
+
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+  if (!prepared_result.UnpackTo(&prepared_statement_result)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementResult");
+  }
+
+  return std::make_shared<PreparedStatement>(impl_, query, prepared_statement_result,
+                                             options);
+}
+
+arrow::Result<std::unique_ptr<FlightInfo>> FlightSqlClient::PreparedStatement::Execute() {
+  if (is_closed_) {
+    return Status::Invalid("Statement already closed.");
+  }
+
+  pb::sql::CommandPreparedStatementQuery execute_query_command;
+
+  execute_query_command.set_prepared_statement_handle(
+      prepared_statement_result_.prepared_statement_handle());
+
+  google::protobuf::Any any;
+  any.PackFrom(execute_query_command);
+
+  const std::string& string = any.SerializeAsString();
+  const FlightDescriptor descriptor = FlightDescriptor::Command(string);
+
+  if (parameter_binding_ && parameter_binding_->num_rows() > 0) {
+    std::unique_ptr<FlightStreamWriter> writer;
+    std::unique_ptr<FlightMetadataReader> reader;
+    ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoPut(
+        *client_, options_, descriptor, parameter_binding_->schema(), &writer, &reader));
+
+    ARROW_RETURN_NOT_OK(writer->WriteRecordBatch(*parameter_binding_));
+    ARROW_RETURN_NOT_OK(writer->DoneWriting());
+    // Wait for the server to ack the result
+    std::shared_ptr<Buffer> buffer;
+    ARROW_RETURN_NOT_OK(reader->ReadMetadata(&buffer));
+  }
+
+  std::unique_ptr<FlightInfo> info;
+  ARROW_RETURN_NOT_OK(
+      internal::FlightClientImpl_GetFlightInfo(*client_, options_, descriptor, &info));
+
+  return std::move(info);
+}
+
+arrow::Result<int64_t> FlightSqlClient::PreparedStatement::ExecuteUpdate() {
+  if (is_closed_) {
+    return Status::Invalid("Statement already closed.");
+  }
+
+  pb::sql::CommandPreparedStatementUpdate command;
+  command.set_prepared_statement_handle(
+      prepared_statement_result_.prepared_statement_handle());
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+
+  if (parameter_binding_ && parameter_binding_->num_rows() > 0) {
+    ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoPut(
+        *client_, options_, descriptor, parameter_binding_->schema(), &writer, &reader));
+    ARROW_RETURN_NOT_OK(writer->WriteRecordBatch(*parameter_binding_));
+  } else {
+    const std::shared_ptr<Schema> schema = arrow::schema({});
+    ARROW_RETURN_NOT_OK(internal::FlightClientImpl_DoPut(*client_, options_, descriptor,
+                                                         schema, &writer, &reader));
+    const auto& record_batch =
+        arrow::RecordBatch::Make(schema, 0, (std::vector<std::shared_ptr<Array>>){});
+    ARROW_RETURN_NOT_OK(writer->WriteRecordBatch(*record_batch));
+  }
+
+  ARROW_RETURN_NOT_OK(writer->DoneWriting());
+  std::shared_ptr<Buffer> metadata;
+  ARROW_RETURN_NOT_OK(reader->ReadMetadata(&metadata));
+  ARROW_RETURN_NOT_OK(writer->Close());
+
+  pb::sql::DoPutUpdateResult result;
+  if (!result.ParseFromArray(metadata->data(), static_cast<int>(metadata->size()))) {
+    return Status::Invalid("Unable to parse DoPutUpdateResult object.");
+  }
+
+  return result.record_count();
+}
+
+Status FlightSqlClient::PreparedStatement::SetParameters(
+    std::shared_ptr<RecordBatch> parameter_binding) {
+  parameter_binding_ = std::move(parameter_binding);
+
+  return Status::OK();
+}
+
+bool FlightSqlClient::PreparedStatement::IsClosed() const { return is_closed_; }
+
+arrow::Result<std::shared_ptr<Schema>>
+FlightSqlClient::PreparedStatement::GetResultSetSchema() {

Review comment:
       IMO, we should parse the schemas up front in the constructor, then make these const getters like `std::shared_ptr<Schema> result_set_schema() const;`. Since we need to handle errors, we could pImpl `PreparedStatement` and handle it in a static factory, or do the parsing in `Prepare`.

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,116 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc client_internal.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}

Review comment:
       (Or was it meant to be ARROW_FLIGHT_LINK_LIBS?)

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Uh, hmm. Is this legal? It feels like we're violating ODR…though it certainly appears to work. 

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+#include "arrow/api.h"

Review comment:
       (Though, please add `<string>`, `<memory>`, etc. for std::string, std::shared_ptr, std::unique_ptr, et. al.)

##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight-sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+using StatementQuery = struct StatementQuery { std::string query; };
+
+using StatementUpdate = struct StatementUpdate { std::string query; };
+
+using StatementQueryTicket = struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+using PreparedStatementQuery = struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+using PreparedStatementUpdate = struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+using GetSqlInfo = struct GetSqlInfo {
+  // TODO: To be implemented.
+};
+
+using GetSchemas = struct GetSchemas {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema_filter_pattern;
+  std::string schema_filter_pattern;
+};
+
+using GetTables = struct GetTables {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema_filter_pattern;
+  std::string schema_filter_pattern;
+  bool has_table_name_filter_pattern;
+  std::string table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+using GetPrimaryKeys = struct GetPrimaryKeys {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema;
+  std::string schema;
+  std::string table;
+};
+
+using GetExportedKeys = struct GetExportedKeys {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema;
+  std::string schema;
+  std::string table;
+};
+
+using GetImportedKeys = struct GetImportedKeys {
+  bool has_catalog;
+  std::string catalog;
+  bool has_schema;
+  std::string schema;
+  std::string table;
+};
+
+using GetCrossReference = struct GetCrossReference {
+  bool has_pk_catalog;
+  std::string pk_catalog;
+  bool has_pk_schema;
+  std::string pk_schema;
+  std::string pk_table;
+  bool has_fk_catalog;
+  std::string fk_catalog;
+  bool has_fk_schema;
+  std::string fk_schema;
+  std::string fk_table;
+};
+
+using ActionCreatePreparedStatementRequest = struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+using ActionClosePreparedStatementRequest = struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+using ActionCreatePreparedStatementResult = struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+class FlightSqlServerBase : public FlightServerBase {

Review comment:
       I think this is needed for Windows?

##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,233 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl;
+}
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+ private:
+  std::shared_ptr<internal::FlightClientImpl> impl_;
+
+ public:
+  class PreparedStatement;
+
+  explicit FlightSqlClient(std::shared_ptr<internal::FlightClientImpl> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket) const;
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types) const;
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table) const;
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options) const;
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(
+      const FlightCallOptions& options, const std::vector<int>& sql_info) const;
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(
+      const FlightCallOptions& options,
+      const std::vector<pb::sql::SqlInfo>& sql_info) const;
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  explicit FlightSqlClient(std::unique_ptr<FlightClient> client);
+
+  class PreparedStatement {
+    std::shared_ptr<internal::FlightClientImpl> client_;
+    FlightCallOptions options_;
+    pb::sql::ActionCreatePreparedStatementResult prepared_statement_result_;
+    std::shared_ptr<RecordBatch> parameter_binding_;
+    bool is_closed_;
+
+   public:
+    /// \brief Constructor for the PreparedStatement class.
+    /// \param[in] query      The query that will be executed.
+    PreparedStatement(
+        std::shared_ptr<internal::FlightClientImpl> client_, const std::string& query,
+        pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,

Review comment:
       This is still leaking the Protobuf types into the public API - perhaps this class needs to be pImpl'd?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r747031540



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       Though the tests do all fail in general, so maybe it's just a different symptom.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-968991739


   > Hey @lidavidm , about your question:
   > 
   > > Actually, why not make GetFlightInfoForCommand and GetFlightInfo protected methods?
   > 
   > Adding GetFlightInfoForCommand to the client header would leak `google::protobuf::Message`
   
   Ah, right…thanks for pointing that out. I suppose we could pImpl it but we'd still have to have some protected methods for mocking. It's fine as is then.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-968990543


   Hey @lidavidm , about your question:
   
   > Actually, why not make GetFlightInfoForCommand and GetFlightInfo protected methods?
   
   Adding GetFlightInfoForCommand to the client header would leak `google::protobuf::Message`


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742287999



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       The intent is that the library build and unit test build compile and link client.cc and client_test.cc respectively. These two files shouldn't be passed to the same linker run at once.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       The intent is that the library build and unit test build compile and link client.cc and client_test.cc respectively. These two files shouldn't be passed to the same linker run at once.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742320867



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Both libarrow_flight_sql.so and client_test.cc.o have symbols for FlightClientImpl for me. That said, they're marked as weak symbols, and presumably the one in the program takes precedence. (Confirmed with LD_DEBUG.)
   
   This works and I'm not going to hold this up, however, it is rather magical and it's worth at least a comment explaining the intent of FlightClientImpl.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742376945



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       (Sorry - I want to try some alternative approaches but haven't found the time. At this rate it may be Friday before I can get into things…)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r743911807



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       This appears to fix it for me, by avoiding linking Protobuf in multiple times:
   
   @rafael-telles does this work for you?
   
   ```diff
   diff --git a/cpp/src/arrow/flight/CMakeLists.txt b/cpp/src/arrow/flight/CMakeLists.txt
   index 309e5a968..66776424e 100644
   --- a/cpp/src/arrow/flight/CMakeLists.txt
   +++ b/cpp/src/arrow/flight/CMakeLists.txt
   @@ -27,11 +27,14 @@ endif()
    
    if(ARROW_TEST_LINKAGE STREQUAL "static")
      set(ARROW_FLIGHT_TEST_LINK_LIBS
   -      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
   +      arrow_flight_static
   +      arrow_flight_testing_static
   +      ${ARROW_FLIGHT_STATIC_LINK_LIBS}
   +      gRPC::grpc++
          ${ARROW_TEST_LINK_LIBS})
    else()
      set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
   -                                  ${ARROW_TEST_LINK_LIBS})
   +                                  gRPC::grpc++ ${ARROW_TEST_LINK_LIBS})
    endif()
    
    # TODO(wesm): Protobuf shared vs static linking
   @@ -165,6 +168,7 @@ add_arrow_lib(arrow_flight
                  ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
                  SHARED_LINK_LIBS
                  arrow_shared
   +              SHARED_PRIVATE_LINK_LIBS
                  ${ARROW_FLIGHT_LINK_LIBS}
                  STATIC_LINK_LIBS
                  arrow_static
   diff --git a/cpp/src/arrow/flight/flight_sql/CMakeLists.txt b/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   index fd453ccc5..8fd852909 100644
   --- a/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   +++ b/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   @@ -36,7 +36,8 @@ set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENER
    
    add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
    
   -set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc client_internal.cc)
   +set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc client_internal.cc
   +                          "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
    
    add_arrow_lib(arrow_flight_sql
                  CMAKE_PACKAGE_NAME
   @@ -51,10 +52,13 @@ add_arrow_lib(arrow_flight_sql
                  "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
                  DEPENDENCIES
                  flight_sql_protobuf_gen
   +              toolchain
                  SHARED_LINK_FLAGS
                  ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
                  SHARED_LINK_LIBS
                  arrow_flight_shared
   +              SHARED_PRIVATE_LINK_LIBS
   +              ${ARROW_PROTOBUF_LIBPROTOBUF}
                  STATIC_LINK_LIBS
                  arrow_flight_static)
    
   @@ -75,7 +79,6 @@ target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
    add_arrow_test(flight_sql_client_test
                   SOURCES
                   client_test.cc
   -               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
                   STATIC_LINK_LIBS
                   ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
                   LABELS
   @@ -85,7 +88,6 @@ add_arrow_test(flight_sql_server_test
                   SOURCES
                   server_test.cc
                   client_internal.cc
   -               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
                   STATIC_LINK_LIBS
                   ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
                   LABELS
   @@ -102,8 +104,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
                     example/sqlite_statement.cc
                     example/sqlite_statement_batch_reader.cc
                     example/sqlite_server.cc
   -                 example/sqlite_tables_schema_batch_reader.cc
   -                 "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
   +                 example/sqlite_tables_schema_batch_reader.cc)
      target_link_libraries(flight_sql_test_server
                            PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}
                                    ${SQLite3_LIBRARIES})
   diff --git a/cpp/vcpkg.json b/cpp/vcpkg.json
   index 11ce5250d..1aee71eb8 100644
   --- a/cpp/vcpkg.json
   +++ b/cpp/vcpkg.json
   @@ -17,7 +17,9 @@
        "benchmark",
        "boost-filesystem",
        "boost-multiprecision",
   +    "boost-process",
        "boost-system",
   +    "boost-uuid",
        "brotli",
        "bzip2",
        "c-ares",
   @@ -40,8 +42,5 @@
        "zlib",
        "zstd"
      ],
   -  "overrides": [
   -    { "name": "gtest", "version": "1.10.0", "port-version": 4 }
   -  ],
   -  "builtin-baseline": "b5865bfeba430cd44063fc54a45a8861195a715f"
   +  "builtin-baseline": "85b31152df8da18be5ec2b0dbd7b39b0d2404db4"
    }
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734798223



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \param schema   The parameter schema from the query.
+  /// \return         Status.
+  Status GetParameterSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \param schema   The ResultSet schema from the query.
+  /// \return         Status.
+  Status GetResultSetSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding_   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.
+  /// \return Status.
+  Status Close();
+
+  /// \brief Checks if the prepared statement is closed.
+  /// \return The state of the prepared statement.
+  bool IsClosed() const;
+};
+
+/// \brief Flight client with Flight SQL semantics.
+template <class T = arrow::flight::FlightClient>
+class FlightSqlClientT {
+ public:
+  explicit FlightSqlClientT(std::unique_ptr<T>& client);
+
+  ~FlightSqlClientT();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset
+  /// \return Status.
+  Status Execute(const FlightCallOptions& options, const std::string& query,
+                 std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] rows        The quantity of rows affected by the operation.
+  /// \return Status.
+  Status ExecuteUpdate(const FlightCallOptions& options, const std::string& query,
+                       int64_t* rows) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset.
+  /// \return Status.
+  Status GetCatalogs(const FlightCallOptions& options,
+                     std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \param[out] flight_info           The FlightInfo describing where to access the
+  ///                                   dataset.
+  /// \return Status.
+  Status GetSchemas(const FlightCallOptions& options, const std::string* catalog,
+                    const std::string* schema_filter_pattern,
+                    std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \param[out] stream the returned RecordBatchReader
+  /// \return Status
+  Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream) const;
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \param[out] flight_info             The FlightInfo describing where to access the
+  ///                                     dataset.
+  /// \return Status.
+  Status GetTables(const FlightCallOptions& options, const std::string* catalog,

Review comment:
       Yes, null and empty are treated differently on JDBC, so we wanted to differentiate them on Flight SQL too




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735850402



##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client = new FlightSqlClient(client);
+  }
+
+  void TearDown() override {
+    server->Stop();
+
+    free(server);
+    free(sql_client);
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(sql_client->Execute({}, "SELECT * FROM intTable", &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  DECLARE_ARRAY(id_array, Int64, ({1, 2, 3}));
+  DECLARE_ARRAY(keyname_array, String, ({"one", "zero", "negative one"}));
+  DECLARE_ARRAY(value_array, Int64, ({1, 0, -1}));
+  DECLARE_ARRAY(foreignId_array, Int64, ({1, 1, 1}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::unique_ptr<FlightInfo> flight_info;
+  std::vector<std::string> table_types;
+  ASSERT_OK(sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types,
+                                  &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  DECLARE_NULL_ARRAY(catalog_name, String, 3);
+  DECLARE_NULL_ARRAY(schema_name, String, 3);
+  DECLARE_ARRAY(table_name, String,
+                ({
+                    "foreignTable",
+                    "intTable",
+                    "sqlite_sequence",
+                }));
+  DECLARE_ARRAY(table_type, String, ({"table", "table", "table"}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  ASSERT_TRUE(expected_table->Equals(*table));

Review comment:
       Ah, actually, it seems the tests are flaky - the failing tests change every time. (Also, this is with the generated Protobuf sources still being compiled into the test executable.)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-952358889


   I see, thanks. I'll try with some more build configurations.
   
   Do you have the output from CMake to share (if it's not sensitive)? It might help make sure I have my setup/dependencies the same way as yours.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r738758362



##########
File path: cpp/src/arrow/flight/flight-sql/test_app_cli.cc
##########
@@ -0,0 +1,200 @@
+// 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/array/builder_binary.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/io/memory.h>
+#include <arrow/pretty_print.h>
+#include <arrow/status.h>
+#include <arrow/table.h>
+#include <gflags/gflags.h>
+
+#include <boost/algorithm/string.hpp>
+#include <iostream>
+#include <memory>
+
+using arrow::Result;
+using arrow::Schema;
+using arrow::Status;
+using arrow::flight::ClientAuthHandler;
+using arrow::flight::FlightCallOptions;
+using arrow::flight::FlightClient;
+using arrow::flight::FlightDescriptor;
+using arrow::flight::FlightEndpoint;
+using arrow::flight::FlightInfo;
+using arrow::flight::FlightStreamChunk;
+using arrow::flight::FlightStreamReader;
+using arrow::flight::Location;
+using arrow::flight::Ticket;
+using arrow::flight::sql::FlightSqlClient;
+
+DEFINE_string(host, "localhost", "Host to connect to");
+DEFINE_int32(port, 32010, "Port to connect to");
+DEFINE_string(username, "", "Username");
+DEFINE_string(password, "", "Password");
+
+DEFINE_string(command, "", "Method to run");
+DEFINE_string(query, "", "Query");
+DEFINE_string(catalog, "", "Catalog");
+DEFINE_string(schema, "", "Schema");
+DEFINE_string(table, "", "Table");
+
+Status PrintResultsForEndpoint(const FlightSqlClient& client,
+                               const FlightCallOptions& call_options,
+                               const FlightEndpoint& endpoint) {
+  std::unique_ptr<FlightStreamReader> stream;
+  ARROW_RETURN_NOT_OK(client.DoGet(call_options, endpoint.ticket, &stream));
+
+  const arrow::Result<std::shared_ptr<Schema>>& schema = stream->GetSchema();
+  ARROW_RETURN_NOT_OK(schema);
+
+  std::cout << "Schema:" << std::endl;
+  std::cout << schema->get()->ToString() << std::endl << std::endl;
+
+  std::cout << "Results:" << std::endl;
+
+  FlightStreamChunk chunk;
+  int64_t num_rows = 0;
+
+  while (true) {
+    ARROW_RETURN_NOT_OK(stream->Next(&chunk));
+    if (!(chunk.data != nullptr)) {
+      break;
+    }
+    std::cout << chunk.data->ToString() << std::endl;
+    num_rows += chunk.data->num_rows();
+  }
+
+  std::cout << "Total: " << num_rows << std::endl;
+
+  return Status::OK();
+}
+
+Status PrintResults(FlightSqlClient& client, const FlightCallOptions& call_options,
+                    const std::unique_ptr<FlightInfo>& info) {
+  const std::vector<FlightEndpoint>& endpoints = info->endpoints();
+
+  for (size_t i = 0; i < endpoints.size(); i++) {
+    std::cout << "Results from endpoint " << i + 1 << " of " << endpoints.size()
+              << std::endl;
+    ARROW_RETURN_NOT_OK(PrintResultsForEndpoint(client, call_options, endpoints[i]));
+  }
+
+  return Status::OK();
+}
+
+Status RunMain() {
+  std::unique_ptr<FlightClient> client;
+  Location location;
+  ARROW_RETURN_NOT_OK(Location::ForGrpcTcp(fLS::FLAGS_host, fLI::FLAGS_port, &location));
+  ARROW_RETURN_NOT_OK(FlightClient::Connect(location, &client));
+
+  FlightCallOptions call_options;
+
+  if (!fLS::FLAGS_username.empty() || !fLS::FLAGS_password.empty()) {
+    Result<std::pair<std::string, std::string>> bearer_result =
+        client->AuthenticateBasicToken({}, fLS::FLAGS_username, fLS::FLAGS_password);
+    ARROW_RETURN_NOT_OK(bearer_result);
+
+    call_options.headers.push_back(bearer_result.ValueOrDie());
+  }
+
+  FlightSqlClient sqlClient(client);
+
+  if (fLS::FLAGS_command == "ExecuteUpdate") {
+    int64_t rows;
+    ARROW_RETURN_NOT_OK(sqlClient.ExecuteUpdate(call_options, fLS::FLAGS_query, &rows));
+
+    std::cout << "Result: " << rows << std::endl;
+
+    return Status::OK();
+  }
+
+  std::unique_ptr<FlightInfo> info;
+
+  if (fLS::FLAGS_command == "Execute") {

Review comment:
       Yes! Removed the explicit namespaces




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-954214713


   That's OK! Now that we addresses most of the other comments I will try to solve this too. Thank you so much!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles edited a comment on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles edited a comment on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-956457180


   > Regarding the Protobuf issue: I switched to vcpkg as that appears to be what you use, but I can't replicate still. What OS and compiler are you using?
   
   @lidavidm , yes, I am using vcpkg.
   
   ```
   Linux Mint 20.2, 
   cmake version 3.16.3
   g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
   gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
   ```
   
   Thanks for your help @lidavidm , please let me know if any other info is helpful! Working on the other comments
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r745862198



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       That's a good idea! They could be made protected methods too.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r762022080



##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -123,24 +127,35 @@ class SqlInfoDenseUnionValidator {
   SqlInfoDenseUnionValidator& operator=(const SqlInfoDenseUnionValidator&) = delete;
 };
 
-std::unique_ptr<TestServer> server;
-std::unique_ptr<FlightSqlClient> sql_client;
+class TestFlightSqlServer : public ::testing::Test {
+ public:
+  std::unique_ptr<FlightSqlClient> sql_client;
+
+  arrow::Result<int64_t> ExecuteCountQuery(const std::string& query) {
+    ARROW_ASSIGN_OR_RAISE(auto flight_info, sql_client->Execute({}, query));
+
+    ARROW_ASSIGN_OR_RAISE(auto stream,
+                          sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+    std::shared_ptr<Table> table;
+    ARROW_RETURN_NOT_OK(stream->ReadAll(&table));
+
+    const std::shared_ptr<Array>& result_array = table->column(0)->chunk(0);
+    ARROW_ASSIGN_OR_RAISE(auto count_scalar, result_array->GetScalar(0));
+
+    return reinterpret_cast<Int64Scalar&>(*count_scalar).value;
+  }
 
-class TestFlightSqlServer : public ::testing::Environment {
  protected:
   void SetUp() override {
-    server.reset(new TestServer("flight_sql_test_server"));
-    server->Start();
-    for (int i = 0; i < 100; i++) {
-      std::this_thread::sleep_for(std::chrono::milliseconds(10));
-      if (server->IsRunning()) {
-        break;
-      }
-    }
-    ASSERT_TRUE(server->IsRunning());
+    unix_sock = std::tmpnam(nullptr);
+    server_thread.reset(new std::thread(RunServer, this));
+
+    std::unique_lock<std::mutex> lk(server_ready_m);
+    server_ready_cv.wait(lk);
 
     std::stringstream ss;
-    ss << "grpc://localhost:" << server->port();
+    ss << "grpc+unix://" << unix_sock;

Review comment:
       I see, reverted this to keep using TCP




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756037496



##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.h
##########
@@ -0,0 +1,87 @@
+// 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.
+
+#pragma once
+
+#include "arrow/flight/sql/sql_info_types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+/// \brief Auxiliary class used to populate GetSqlInfo's DenseUnionArray with different
+/// data types.
+class SqlInfoResultAppender {
+ public:
+  /// \brief Appends a string to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::string& value);
+
+  /// \brief Appends a bool to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(bool value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int64_t value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.

Review comment:
       "int32_t"?

##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.h
##########
@@ -0,0 +1,87 @@
+// 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.
+
+#pragma once
+
+#include "arrow/flight/sql/sql_info_types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+/// \brief Auxiliary class used to populate GetSqlInfo's DenseUnionArray with different
+/// data types.
+class SqlInfoResultAppender {
+ public:
+  /// \brief Appends a string to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::string& value);
+
+  /// \brief Appends a bool to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(bool value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int64_t value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int32_t value);
+
+  /// \brief Appends a string list to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::vector<std::string>& value);
+
+  /// \brief Appends a int32 to int32 list map to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::unordered_map<int32_t, std::vector<int32_t>>& value);
+
+  /// \brief Creates a Variant visitor that appends data to given
+  /// DenseUnionBuilder. \param[in] value_builder  DenseUnionBuilder to append data to.
+  explicit SqlInfoResultAppender(DenseUnionBuilder& value_builder);
+
+  SqlInfoResultAppender(const SqlInfoResultAppender&) = delete;
+  SqlInfoResultAppender(SqlInfoResultAppender&&) = delete;
+  SqlInfoResultAppender& operator=(const SqlInfoResultAppender&) = delete;
+
+ private:
+  DenseUnionBuilder& value_builder_;

Review comment:
       Make this a pointer since it's mutable?

##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.h
##########
@@ -0,0 +1,87 @@
+// 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.
+
+#pragma once
+
+#include "arrow/flight/sql/sql_info_types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+/// \brief Auxiliary class used to populate GetSqlInfo's DenseUnionArray with different
+/// data types.
+class SqlInfoResultAppender {
+ public:
+  /// \brief Appends a string to the DenseUnionBuilder.

Review comment:
       Nit: use infinitives, e.g. "Append" not "Appends".

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);

Review comment:
       Is it `std::string*` because the filter is optional? If so, should we simply use an empty string for the default or does that have another meaning?
   
   (also, if those are optional, then should we add a default parameter value?)

##########
File path: cpp/src/arrow/flight/sql/server.h
##########
@@ -0,0 +1,495 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/server.h"
+#include "arrow/flight/sql/server.h"
+#include "arrow/flight/sql/sql_info_types.h"
+#include "arrow/util/optional.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  std::vector<int32_t> info;
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;
+  util::optional<std::string> fk_catalog;
+  util::optional<std::string> fk_schema;
+  std::string fk_table;
+};
+
+struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+/// \brief A utility function to create a ticket for a statement query.
+///        Intended for Flight SQL server implementations.

Review comment:
       What is a ticket? Perhaps briefly explain what it is meant for?

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+

Review comment:
       Can you ensure all module-private functions below are in the anonymous namespace (so that their symbols don't get exported at all)?

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;

Review comment:
       Just for the record, no need to change this, but you could probably shorten it by using aggregate construction:
   ```c++
   return GetImportedKeys{
       PROPERTY_TO_OPTIONAL(command, catalog),
       PROPERTY_TO_OPTIONAL(command, schema),
       command.table()};
   ```

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any, const SqlInfoResultMap& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::ListActions(const ServerCallContext& context,
+                                        std::vector<ActionType>* actions) {
+  *actions = {FlightSqlServerBase::kCreatePreparedStatementActionType,
+              FlightSqlServerBase::kClosePreparedStatementActionType};
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::DoAction(const ServerCallContext& context,
+                                     const Action& action,
+                                     std::unique_ptr<ResultStream>* result_stream) {
+  if (action.type == FlightSqlServerBase::kCreatePreparedStatementActionType.type) {
+    google::protobuf::Any any_command;
+    if (!any_command.ParseFromArray(action.body->data(),
+                                    static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionCreatePreparedStatementRequest internal_command,
+                          ParseActionCreatePreparedStatementRequest(any_command));
+    ARROW_ASSIGN_OR_RAISE(auto result, CreatePreparedStatement(context, internal_command))
+
+    pb::sql::ActionCreatePreparedStatementResult action_result;
+    action_result.set_prepared_statement_handle(result.prepared_statement_handle);
+    if (result.dataset_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_dataset_schema,
+                            ipc::SerializeSchema(*result.dataset_schema))
+      action_result.set_dataset_schema(serialized_dataset_schema->ToString());
+    }
+    if (result.parameter_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_parameter_schema,
+                            ipc::SerializeSchema(*result.parameter_schema))
+      action_result.set_parameter_schema(serialized_parameter_schema->ToString());
+    }
+
+    google::protobuf::Any any;
+    any.PackFrom(action_result);
+
+    auto buf = Buffer::FromString(any.SerializeAsString());
+    *result_stream = std::unique_ptr<ResultStream>(new SimpleResultStream({Result{buf}}));
+
+    return Status::OK();
+  } else if (action.type == FlightSqlServerBase::kClosePreparedStatementActionType.type) {
+    google::protobuf::Any any;
+    if (!any.ParseFromArray(action.body->data(), static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionClosePreparedStatementRequest internal_command,
+                          ParseActionClosePreparedStatementRequest(any));
+
+    return ClosePreparedStatement(context, internal_command, result_stream);
+  }
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCatalogs(const ServerCallContext& context,
+                                                  const FlightDescriptor& descriptor,
+                                                  std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCatalogs(const ServerCallContext& context,
+                                          std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoStatement(const ServerCallContext& context,
+                                                   const StatementQuery& command,
+                                                   const FlightDescriptor& descriptor,
+                                                   std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetStatement(const ServerCallContext& context,
+                                           const StatementQueryTicket& command,
+                                           std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                                 const GetSqlInfo& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  assert(info != nullptr);
+
+  if (sql_info_id_to_result_.empty()) {
+    return Status::NotImplemented("GetFlightInfoSqlInfo not implemented");
+  }
+
+  std::vector<FlightEndpoint> endpoints{FlightEndpoint{{descriptor.cmd}, {}}};
+  ARROW_ASSIGN_OR_RAISE(auto result, FlightInfo::Make(*SqlSchema::GetSqlInfoSchema(),
+                                                      descriptor, endpoints, -1, -1))
+
+  *info = std::unique_ptr<FlightInfo>(new FlightInfo(result));
+
+  return Status::OK();
+}
+
+void FlightSqlServerBase::RegisterSqlInfo(int32_t id, const SqlInfoResult& result) {
+  sql_info_id_to_result_[id] = result;
+}
+
+Status FlightSqlServerBase::DoGetSqlInfo(const ServerCallContext& context,
+                                         const GetSqlInfo& command,
+                                         std::unique_ptr<FlightDataStream>* result) {
+  DCHECK(result);
+
+  MemoryPool* memory_pool = default_memory_pool();
+  UInt32Builder name_field_builder(memory_pool);
+  std::unique_ptr<ArrayBuilder> value_field_builder;
+  const auto& value_field_type = std::static_pointer_cast<DenseUnionType>(

Review comment:
       Use `checked_pointer_cast` from `arrow/util/checked_cast.h`, to enable type checks in debug mode.

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -0,0 +1,783 @@
+// 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.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/api.h"
+#include "arrow/flight/sql/example/sqlite_server.h"
+#include "arrow/flight/test_util.h"
+#include "arrow/flight/types.h"
+#include "arrow/testing/gtest_util.h"
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+/// \brief Auxiliary variant visitor used to assert that GetSqlInfo's values are
+/// correctly placed on its DenseUnionArray
+class SqlInfoDenseUnionValidator {
+ private:
+  const DenseUnionScalar& data;
+
+ public:
+  /// \brief Asserts that the current DenseUnionScalar equals to given string value
+  void operator()(const std::string& string_value) const {
+    const auto& scalar = dynamic_cast<const StringScalar&>(*data.value);
+    ASSERT_EQ(string_value, scalar.ToString());
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given bool value
+  void operator()(const bool bool_value) const {
+    const auto& scalar = dynamic_cast<const BooleanScalar&>(*data.value);
+    ASSERT_EQ(bool_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int64_t value
+  void operator()(const int64_t bigint_value) const {
+    const auto& scalar = dynamic_cast<const Int64Scalar&>(*data.value);
+    ASSERT_EQ(bigint_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32_t value
+  void operator()(const int32_t int32_bitmask) const {
+    const auto& scalar = dynamic_cast<const Int32Scalar&>(*data.value);
+    ASSERT_EQ(int32_bitmask, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given string list
+  void operator()(const std::vector<std::string>& string_list) const {
+    const auto& array = dynamic_cast<const StringArray&>(
+        *(dynamic_cast<const ListScalar&>(*data.value).value));
+
+    ASSERT_EQ(string_list.size(), array.length());
+
+    for (size_t index = 0; index < string_list.size(); index++) {
+      ASSERT_EQ(string_list[index], array.GetString(index));
+    }
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32 to int32 list
+  /// map.
+  void operator()(const std::unordered_map<int32_t, std::vector<int32_t>>&
+                      int32_to_int32_list) const {
+    const auto& struct_array = dynamic_cast<const StructArray&>(
+        *dynamic_cast<const MapScalar&>(*data.value).value);
+    const auto& keys = dynamic_cast<const Int32Array&>(*struct_array.field(0));
+    const auto& values = dynamic_cast<const ListArray&>(*struct_array.field(1));
+
+    // Assert that the given map has the right size
+    ASSERT_EQ(int32_to_int32_list.size(), keys.length());
+
+    // For each element on given MapScalar, assert it matches the argument
+    for (int i = 0; i < keys.length(); i++) {
+      ASSERT_OK_AND_ASSIGN(const auto& key_scalar, keys.GetScalar(i));
+      int32_t sql_info_id = dynamic_cast<const Int32Scalar&>(*key_scalar).value;
+
+      // Assert the key (SqlInfo id) exists
+      ASSERT_TRUE(int32_to_int32_list.count(sql_info_id));
+
+      const std::vector<int32_t>& expected_int32_list =
+          int32_to_int32_list.at(sql_info_id);
+
+      // Assert the value (int32 list) has the correct size
+      ASSERT_EQ(expected_int32_list.size(), values.value_length(i));
+
+      // For each element on current ListScalar, assert it matches with the argument
+      for (size_t j = 0; j < expected_int32_list.size(); j++) {
+        ASSERT_OK_AND_ASSIGN(auto list_item_scalar,
+                             values.values()->GetScalar(values.value_offset(i) + j));
+        const auto& list_item = dynamic_cast<const Int32Scalar&>(*list_item_scalar).value;
+        ASSERT_EQ(expected_int32_list[j], list_item);
+      }
+    }
+  }
+
+  explicit SqlInfoDenseUnionValidator(const DenseUnionScalar& data) : data(data) {}
+
+  SqlInfoDenseUnionValidator(const SqlInfoDenseUnionValidator&) = delete;
+  SqlInfoDenseUnionValidator(SqlInfoDenseUnionValidator&&) = delete;
+  SqlInfoDenseUnionValidator& operator=(const SqlInfoDenseUnionValidator&) = delete;
+};
+
+std::unique_ptr<TestServer> server;
+std::unique_ptr<FlightSqlClient> sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server.reset(new TestServer("flight_sql_test_server"));
+    server->Start();
+    for (int i = 0; i < 100; i++) {
+      std::this_thread::sleep_for(std::chrono::milliseconds(10));
+      if (server->IsRunning()) {
+        break;
+      }
+    }
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+    server->Stop();
+    server.reset();
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array;
+  std::shared_ptr<Array> keyname_array;
+  std::shared_ptr<Array> value_array;
+  std::shared_ptr<Array> foreignId_array;
+  ArrayFromVector<Int64Type>({1, 2, 3}, &id_array);
+  ArrayFromVector<StringType, std::string>({"one", "zero", "negative one"},
+                                           &keyname_array);
+  ArrayFromVector<Int64Type>({1, 0, -1}, &value_array);
+  ArrayFromVector<Int64Type>({1, 1, 1}, &foreignId_array);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::vector<std::string> table_types;
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {"foreignTable", "intTable", "sqlite_sequence"}, &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableFilter) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableTypesFilter) {
+  std::vector<std::string> table_types{"index"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_TRUE(table->schema()->Equals(SqlSchema::GetTablesSchema()));
+
+  ASSERT_EQ(table->num_rows(), 0);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithUnexistenceTableTypeFilter) {
+  std::vector<std::string> table_types{"table"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {
+          "foreignTable",
+          "intTable",
+          "sqlite_sequence",
+      },
+      &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithIncludedSchemas) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             true, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Schema> schema_table = arrow::schema(
+      {arrow::field("id", int64(), true), arrow::field("keyName", utf8(), true),
+       arrow::field("value", int64(), true), arrow::field("foreignId", int64(), true)});
+
+  const arrow::Result<std::shared_ptr<Buffer>>& value =
+      ipc::SerializeSchema(*schema_table);
+  std::shared_ptr<Buffer> schema_buffer;
+
+  ASSERT_OK_AND_ASSIGN(schema_buffer, value);
+  std::shared_ptr<Array> table_schema;
+
+  ArrayFromVector<BinaryType, std::string>({schema_buffer->ToString()}, &table_schema);
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetTablesSchemaWithIncludedSchema(),
+                  {catalog_name, schema_name, table_name, table_type, table_schema});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetCatalogs) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetCatalogs({}));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema = SqlSchema::GetCatalogsSchema();
+
+  ASSERT_TRUE(table->schema()->Equals(*expected_schema));

Review comment:
       Please use `AssertSchemaEqual`

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.

Review comment:
       Is this an optional parameter? If so, perhaps it can have a default value?

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_server.cc
##########
@@ -0,0 +1,684 @@
+// 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/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid_io.hpp>
+
+#include "arrow/api.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+#include "arrow/flight/sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/sql/example/sqlite_tables_schema_batch_reader.h"
+#include "arrow/flight/sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+namespace {
+
+/// \brief Gets a SqliteStatement by given handle
+arrow::Result<std::shared_ptr<SqliteStatement>> GetStatementByHandle(
+    const std::map<boost::uuids::uuid, std::shared_ptr<SqliteStatement>>&
+        prepared_statements,
+    const std::string& handle) {
+  const auto& uuid = boost::lexical_cast<boost::uuids::uuid>(handle);
+
+  auto search = prepared_statements.find(uuid);
+  if (search == prepared_statements.end()) {
+    return Status::Invalid("Prepared statement not found");
+  }
+
+  return search->second;
+}
+
+std::string PrepareQueryForGetTables(const GetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.catalog.has_value()) {
+    table_query << " and catalog_name='" << command.catalog.value() << "'";
+  }
+
+  if (command.schema_filter_pattern.has_value()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern.value()
+                << "'";
+  }
+
+  if (command.table_name_filter_pattern.has_value()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern.value()
+                << "'";
+  }
+
+  if (!command.table_types.empty()) {
+    table_query << " and table_type IN (";
+    size_t size = command.table_types.size();
+    for (size_t i = 0; i < size; i++) {
+      table_query << "'" << command.table_types[i] << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt, FlightMessageReader* reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = static_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = static_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = static_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer = static_cast<StringScalar&>(*holder).value;
+            sqlite3_bind_text(stmt, c + 1, reinterpret_cast<const char*>(buffer->data()),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer = static_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+}  // namespace
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {

Review comment:
       Why use `boost::iequals`? Is it actually possible to get different casings here?

##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.h
##########
@@ -0,0 +1,87 @@
+// 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.
+
+#pragma once
+
+#include "arrow/flight/sql/sql_info_types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+/// \brief Auxiliary class used to populate GetSqlInfo's DenseUnionArray with different
+/// data types.
+class SqlInfoResultAppender {
+ public:
+  /// \brief Appends a string to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::string& value);
+
+  /// \brief Appends a bool to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(bool value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int64_t value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int32_t value);
+
+  /// \brief Appends a string list to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::vector<std::string>& value);
+
+  /// \brief Appends a int32 to int32 list map to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::unordered_map<int32_t, std::vector<int32_t>>& value);

Review comment:
       Use `SqlInfoResultMap`?

##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.cc
##########
@@ -0,0 +1,101 @@
+// 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/sql_info_internal.h"
+
+#include "arrow/api.h"

Review comment:
       Better not to include `arrow/api.h` which tends to include far too much at once. I assume you mostly need `builder.h`?

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_statement.h
##########
@@ -0,0 +1,77 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include <memory>
+#include <string>
+
+#include "arrow/type_fwd.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+class SqliteStatement {
+ public:
+  /// \brief Creates a SQLite3 statement.
+  /// \param[in] db        SQLite3 database instance.
+  /// \param[in] sql       SQL statement.
+  /// \return              A SqliteStatement object.
+  static arrow::Result<std::shared_ptr<SqliteStatement>> Create(sqlite3* db,
+                                                                const std::string& sql);
+
+  ~SqliteStatement();
+
+  /// \brief Creates an Arrow Schema based on the results of this statement.
+  /// \param[out] schema   The resulting Schema.
+  /// \return              Status.
+  Status GetSchema(std::shared_ptr<Schema>* schema) const;
+
+  /// \brief Steps on underlying sqlite3_stmt.
+  /// \param[out] rc   The resulting return code from SQLite.
+  /// \return          Status.
+  Status Step(int* rc);

Review comment:
       Return `Result<int>` instead of out-parameters.
   (same for other methods below and above)

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.

Review comment:
       Does this parameter actually make a difference? (is it much more costly to include the schema?)

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,

Review comment:
       Ideally you don't have to qualify `arrow::Result`, just use `Result`.

##########
File path: cpp/src/arrow/flight/sql/server.h
##########
@@ -0,0 +1,495 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/server.h"
+#include "arrow/flight/sql/server.h"
+#include "arrow/flight/sql/sql_info_types.h"
+#include "arrow/util/optional.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  std::vector<int32_t> info;
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;
+  util::optional<std::string> fk_catalog;
+  util::optional<std::string> fk_schema;
+  std::string fk_table;
+};
+
+struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+/// \brief A utility function to create a ticket for a statement query.
+///        Intended for Flight SQL server implementations.
+/// \param[in] statement_handle      The statement handle that will originate the ticket.
+/// \return                          The parsed ticket as an string.
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle);
+
+class ARROW_EXPORT FlightSqlServerBase : public FlightServerBase {
+ private:
+  SqlInfoResultMap sql_info_id_to_result_;
+
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType kCreatePreparedStatementActionType =
+      ActionType{"CreatePreparedStatement",
+                 "Creates a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionCreatePreparedStatementRequest\n"
+                 "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType kClosePreparedStatementActionType =
+      ActionType{"ClosePreparedStatement",
+                 "Closes a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionClosePreparedStatementRequest\n"
+                 "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQuery object containing the SQL statement.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const ServerCallContext& context,

Review comment:
       Can this return `Result<std::unique_ptr<FlightInfo>>`?
   
   Same comment for other methods with a single output parameter below.

##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.h
##########
@@ -0,0 +1,87 @@
+// 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.
+
+#pragma once
+
+#include "arrow/flight/sql/sql_info_types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+/// \brief Auxiliary class used to populate GetSqlInfo's DenseUnionArray with different
+/// data types.
+class SqlInfoResultAppender {
+ public:
+  /// \brief Appends a string to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::string& value);
+
+  /// \brief Appends a bool to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(bool value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int64_t value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int32_t value);
+
+  /// \brief Appends a string list to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::vector<std::string>& value);
+
+  /// \brief Appends a int32 to int32 list map to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::unordered_map<int32_t, std::vector<int32_t>>& value);
+
+  /// \brief Creates a Variant visitor that appends data to given
+  /// DenseUnionBuilder. \param[in] value_builder  DenseUnionBuilder to append data to.
+  explicit SqlInfoResultAppender(DenseUnionBuilder& value_builder);
+
+  SqlInfoResultAppender(const SqlInfoResultAppender&) = delete;
+  SqlInfoResultAppender(SqlInfoResultAppender&&) = delete;
+  SqlInfoResultAppender& operator=(const SqlInfoResultAppender&) = delete;
+
+ private:
+  DenseUnionBuilder& value_builder_;
+
+  // Builders for each child on dense union
+  StringBuilder* string_value_builder_;
+  BooleanBuilder* bool_value_builder_;
+  Int64Builder* bigint_value_builder_;
+  Int32Builder* int32_bitmask_builder_;
+  ListBuilder* string_list_builder_;
+  MapBuilder* int32_to_int32_list_builder_;
+
+  enum : int8_t {
+    STRING_VALUE_INDEX = 0,

Review comment:
       No strong feelings about this, but ISTM that `kStringValueIndex` (or perhaps `kStringFieldIndex`) would be more codestyle-compliant.

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, const std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);

Review comment:
       Hmm, instead of passing a bunch of strings, it looks like it would be better to have a dedicated type, e.g.:
   ```c++
   
   struct TablePath {
     std::string catalog;
     std::string schema;
     std::string table;
   };
   
   arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(const FlightCallOptions& options, const TablePath& table);
   
   arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
       const FlightCallOptions& options, const TablePath& from_table, const TablePath& to_table);
   ```
   

##########
File path: cpp/src/arrow/flight/sql/server.h
##########
@@ -0,0 +1,495 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/server.h"
+#include "arrow/flight/sql/server.h"
+#include "arrow/flight/sql/sql_info_types.h"
+#include "arrow/util/optional.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  std::vector<int32_t> info;
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;

Review comment:
       We should strive to be consistent, as elsewhere some `std::string*` pointers are used for those optional parameters.
   I would favour either `util::optional<std::string>`, or simply `std::string` with the convention that empty means omitted (if this is possible).
   
   Also, see other comment about making this more structured, e.g. the `struct TablePath` suggestion (but can name it `TableRef` or anything else :-)).

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, const std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  /// \brief Retrieve the FlightInfo.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] descriptor   The flight descriptior.
+  /// \param[out] info        The flight info with the metadata.
+  /// \return Status.
+  // NOTE: This is public because it is been used by the anonymous
+  // function GetFlightInfoForCommand.
+  virtual Status GetFlightInfo(const FlightCallOptions& options,
+                               const FlightDescriptor& descriptor,
+                               std::unique_ptr<FlightInfo>* info) {
+    return impl_->GetFlightInfo(options, descriptor, info);
+  }
+
+ protected:
+  virtual Status DoPut(const FlightCallOptions& options,
+                       const FlightDescriptor& descriptor,
+                       const std::shared_ptr<Schema>& schema,
+                       std::unique_ptr<FlightStreamWriter>* stream,
+                       std::unique_ptr<FlightMetadataReader>* reader) {
+    return impl_->DoPut(options, descriptor, schema, stream, reader);
+  }
+
+  virtual Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+                       std::unique_ptr<FlightStreamReader>* stream) {
+    return impl_->DoGet(options, ticket, stream);
+  }
+
+  virtual Status DoAction(const FlightCallOptions& options, const Action& action,
+                          std::unique_ptr<ResultStream>* results) {
+    return impl_->DoAction(options, action, results);
+  }
+};
+
+/// \brief PreparedStatement class from flight sql.
+class ARROW_EXPORT PreparedStatement {
+  FlightSqlClient* client_;
+  FlightCallOptions options_;
+  std::string handle_;
+  std::shared_ptr<Schema> dataset_schema_;
+  std::shared_ptr<Schema> parameter_schema_;
+  std::shared_ptr<RecordBatch> parameter_binding_;
+  bool is_closed_;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client                Client object used to make the RPC requests.
+  /// \param[in] handle                Handle for this prepared statement.
+  /// \param[in] dataset_schema        Schema of the resulting dataset.
+  /// \param[in] parameter_schema      Schema of the parameters (if any).
+  /// \param[in] options               RPC-layer hints for this call.
+  PreparedStatement(FlightSqlClient* client, std::string handle,
+                    std::shared_ptr<Schema> dataset_schema,
+                    std::shared_ptr<Schema> parameter_schema, FlightCallOptions options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  /// NOTE: It is best to explicitly close the PreparedStatement, otherwise
+  /// errors can't be caught.
+  ~PreparedStatement();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \return A FlightInfo object representing the stream(s) to fetch.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute();
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \return The number of rows affected.
+  arrow::Result<int64_t> ExecuteUpdate();
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \return The parameter schema from the query.
+  std::shared_ptr<Schema> parameter_schema() const;
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \return The ResultSet schema from the query.
+  std::shared_ptr<Schema> dataset_schema() const;
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.
+  /// \return Status.
+  Status Close();
+
+  /// \brief Checks if the prepared statement is closed.

Review comment:
       "Check"

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, const std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  /// \brief Retrieve the FlightInfo.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] descriptor   The flight descriptior.
+  /// \param[out] info        The flight info with the metadata.
+  /// \return Status.
+  // NOTE: This is public because it is been used by the anonymous
+  // function GetFlightInfoForCommand.
+  virtual Status GetFlightInfo(const FlightCallOptions& options,
+                               const FlightDescriptor& descriptor,
+                               std::unique_ptr<FlightInfo>* info) {
+    return impl_->GetFlightInfo(options, descriptor, info);
+  }
+
+ protected:
+  virtual Status DoPut(const FlightCallOptions& options,
+                       const FlightDescriptor& descriptor,
+                       const std::shared_ptr<Schema>& schema,
+                       std::unique_ptr<FlightStreamWriter>* stream,
+                       std::unique_ptr<FlightMetadataReader>* reader) {
+    return impl_->DoPut(options, descriptor, schema, stream, reader);
+  }
+
+  virtual Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+                       std::unique_ptr<FlightStreamReader>* stream) {
+    return impl_->DoGet(options, ticket, stream);
+  }
+
+  virtual Status DoAction(const FlightCallOptions& options, const Action& action,
+                          std::unique_ptr<ResultStream>* results) {
+    return impl_->DoAction(options, action, results);
+  }
+};
+
+/// \brief PreparedStatement class from flight sql.
+class ARROW_EXPORT PreparedStatement {
+  FlightSqlClient* client_;
+  FlightCallOptions options_;
+  std::string handle_;
+  std::shared_ptr<Schema> dataset_schema_;
+  std::shared_ptr<Schema> parameter_schema_;
+  std::shared_ptr<RecordBatch> parameter_binding_;
+  bool is_closed_;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client                Client object used to make the RPC requests.
+  /// \param[in] handle                Handle for this prepared statement.
+  /// \param[in] dataset_schema        Schema of the resulting dataset.
+  /// \param[in] parameter_schema      Schema of the parameters (if any).
+  /// \param[in] options               RPC-layer hints for this call.
+  PreparedStatement(FlightSqlClient* client, std::string handle,
+                    std::shared_ptr<Schema> dataset_schema,
+                    std::shared_ptr<Schema> parameter_schema, FlightCallOptions options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  /// NOTE: It is best to explicitly close the PreparedStatement, otherwise
+  /// errors can't be caught.
+  ~PreparedStatement();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \return A FlightInfo object representing the stream(s) to fetch.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute();
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \return The number of rows affected.
+  arrow::Result<int64_t> ExecuteUpdate();
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \return The parameter schema from the query.
+  std::shared_ptr<Schema> parameter_schema() const;
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \return The ResultSet schema from the query.
+  std::shared_ptr<Schema> dataset_schema() const;
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.

Review comment:
       This parameter doesn't seem to exist.

##########
File path: cpp/src/arrow/flight/sql/server.h
##########
@@ -0,0 +1,495 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/server.h"
+#include "arrow/flight/sql/server.h"
+#include "arrow/flight/sql/sql_info_types.h"
+#include "arrow/util/optional.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  std::vector<int32_t> info;
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;
+  util::optional<std::string> fk_catalog;
+  util::optional<std::string> fk_schema;
+  std::string fk_table;
+};
+
+struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+/// \brief A utility function to create a ticket for a statement query.
+///        Intended for Flight SQL server implementations.
+/// \param[in] statement_handle      The statement handle that will originate the ticket.
+/// \return                          The parsed ticket as an string.
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle);
+
+class ARROW_EXPORT FlightSqlServerBase : public FlightServerBase {
+ private:
+  SqlInfoResultMap sql_info_id_to_result_;
+
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType kCreatePreparedStatementActionType =
+      ActionType{"CreatePreparedStatement",
+                 "Creates a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionCreatePreparedStatementRequest\n"
+                 "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType kClosePreparedStatementActionType =
+      ActionType{"ClosePreparedStatement",
+                 "Closes a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionClosePreparedStatementRequest\n"
+                 "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQuery object containing the SQL statement.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const ServerCallContext& context,
+                                        const StatementQuery& command,
+                                        const FlightDescriptor& descriptor,
+                                        std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQueryTicket containing the statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetStatement(const ServerCallContext& context,
+                                const StatementQueryTicket& command,
+                                std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for executing an already created prepared statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPreparedStatement(const ServerCallContext& context,
+                                                const PreparedStatementQuery& command,
+                                                const FlightDescriptor& descriptor,
+                                                std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the prepared statement query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetPreparedStatement(const ServerCallContext& context,
+                                        const PreparedStatementQuery& command,

Review comment:
       Hmm... this is more of a high-level question but I'll ask it here.
   
   IIRC, in SQL-land a prepared statement can have placeholders for late-time parameters, e.g. `SELECT x FROM table WHERE col=%0`, and the `%0` value is given when asking to execute the prepared statement. Is there a reason such a scheme doesn't seem to be used here?

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, const std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  /// \brief Retrieve the FlightInfo.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] descriptor   The flight descriptior.
+  /// \param[out] info        The flight info with the metadata.
+  /// \return Status.
+  // NOTE: This is public because it is been used by the anonymous
+  // function GetFlightInfoForCommand.
+  virtual Status GetFlightInfo(const FlightCallOptions& options,

Review comment:
       Can this return `Result<std::unique_ptr<FlightInfo>>` instead of using an out-parameter?

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(

Review comment:
       Nit: can spell `Result` with namespacing it.

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, const std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  /// \brief Retrieve the FlightInfo.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] descriptor   The flight descriptior.
+  /// \param[out] info        The flight info with the metadata.
+  /// \return Status.
+  // NOTE: This is public because it is been used by the anonymous
+  // function GetFlightInfoForCommand.
+  virtual Status GetFlightInfo(const FlightCallOptions& options,
+                               const FlightDescriptor& descriptor,
+                               std::unique_ptr<FlightInfo>* info) {
+    return impl_->GetFlightInfo(options, descriptor, info);
+  }
+
+ protected:
+  virtual Status DoPut(const FlightCallOptions& options,
+                       const FlightDescriptor& descriptor,
+                       const std::shared_ptr<Schema>& schema,
+                       std::unique_ptr<FlightStreamWriter>* stream,
+                       std::unique_ptr<FlightMetadataReader>* reader) {
+    return impl_->DoPut(options, descriptor, schema, stream, reader);
+  }
+
+  virtual Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+                       std::unique_ptr<FlightStreamReader>* stream) {
+    return impl_->DoGet(options, ticket, stream);
+  }
+
+  virtual Status DoAction(const FlightCallOptions& options, const Action& action,
+                          std::unique_ptr<ResultStream>* results) {
+    return impl_->DoAction(options, action, results);
+  }
+};
+
+/// \brief PreparedStatement class from flight sql.
+class ARROW_EXPORT PreparedStatement {
+  FlightSqlClient* client_;
+  FlightCallOptions options_;
+  std::string handle_;
+  std::shared_ptr<Schema> dataset_schema_;
+  std::shared_ptr<Schema> parameter_schema_;
+  std::shared_ptr<RecordBatch> parameter_binding_;
+  bool is_closed_;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client                Client object used to make the RPC requests.
+  /// \param[in] handle                Handle for this prepared statement.
+  /// \param[in] dataset_schema        Schema of the resulting dataset.
+  /// \param[in] parameter_schema      Schema of the parameters (if any).
+  /// \param[in] options               RPC-layer hints for this call.
+  PreparedStatement(FlightSqlClient* client, std::string handle,
+                    std::shared_ptr<Schema> dataset_schema,
+                    std::shared_ptr<Schema> parameter_schema, FlightCallOptions options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  /// NOTE: It is best to explicitly close the PreparedStatement, otherwise
+  /// errors can't be caught.
+  ~PreparedStatement();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \return A FlightInfo object representing the stream(s) to fetch.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute();
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \return The number of rows affected.
+  arrow::Result<int64_t> ExecuteUpdate();
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \return The parameter schema from the query.
+  std::shared_ptr<Schema> parameter_schema() const;
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \return The ResultSet schema from the query.
+  std::shared_ptr<Schema> dataset_schema() const;
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.

Review comment:
       "Close"

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,177 @@
+// 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/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/builder.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                             \
+  case TYPE_CLASS##Type::type_id: {                                               \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                               \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);              \
+    if (string == nullptr) {                                                      \
+      ARROW_RETURN_NOT_OK(                                                        \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());        \
+      break;                                                                      \
+    }                                                                             \
+    ARROW_RETURN_NOT_OK(                                                          \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes)); \
+    break;                                                                        \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK(                                                             \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());             \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes)); \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                        \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);             \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \
+  }
+
+#define FLOAT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                      \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    double value = sqlite3_column_double(STMT, COLUMN);                   \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \
+  }
+
+#define MAX_BATCH_SIZE 1024

Review comment:
       Can you use a `constexpr` instead? e.g. `static constexpr int kMaxBatchSize = 1024`.
   
   (also, put it insinde the namespaces below)

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -0,0 +1,783 @@
+// 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.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/api.h"
+#include "arrow/flight/sql/example/sqlite_server.h"
+#include "arrow/flight/test_util.h"
+#include "arrow/flight/types.h"
+#include "arrow/testing/gtest_util.h"
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+/// \brief Auxiliary variant visitor used to assert that GetSqlInfo's values are
+/// correctly placed on its DenseUnionArray
+class SqlInfoDenseUnionValidator {
+ private:
+  const DenseUnionScalar& data;
+
+ public:
+  /// \brief Asserts that the current DenseUnionScalar equals to given string value
+  void operator()(const std::string& string_value) const {
+    const auto& scalar = dynamic_cast<const StringScalar&>(*data.value);

Review comment:
       Can use `checked_cast` everywhere instead of `dynamic_cast` (though I guess `dynamic_cast` is fine for tests).

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,177 @@
+// 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/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/builder.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                             \
+  case TYPE_CLASS##Type::type_id: {                                               \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                               \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);              \
+    if (string == nullptr) {                                                      \
+      ARROW_RETURN_NOT_OK(                                                        \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());        \
+      break;                                                                      \
+    }                                                                             \
+    ARROW_RETURN_NOT_OK(                                                          \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes)); \
+    break;                                                                        \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK(                                                             \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());             \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes)); \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                        \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);             \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \

Review comment:
       Does this mean a NULL cannot appear in a INT64 column?

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;

Review comment:
       Can you `#undef` this at the end of this file? It is better for unity builds.

##########
File path: cpp/src/arrow/flight/sql/server.h
##########
@@ -0,0 +1,495 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/server.h"
+#include "arrow/flight/sql/server.h"
+#include "arrow/flight/sql/sql_info_types.h"
+#include "arrow/util/optional.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  std::vector<int32_t> info;
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;
+  util::optional<std::string> fk_catalog;
+  util::optional<std::string> fk_schema;
+  std::string fk_table;
+};
+
+struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+/// \brief A utility function to create a ticket for a statement query.
+///        Intended for Flight SQL server implementations.
+/// \param[in] statement_handle      The statement handle that will originate the ticket.
+/// \return                          The parsed ticket as an string.
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle);
+
+class ARROW_EXPORT FlightSqlServerBase : public FlightServerBase {
+ private:
+  SqlInfoResultMap sql_info_id_to_result_;
+
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType kCreatePreparedStatementActionType =
+      ActionType{"CreatePreparedStatement",
+                 "Creates a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionCreatePreparedStatementRequest\n"
+                 "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType kClosePreparedStatementActionType =
+      ActionType{"ClosePreparedStatement",
+                 "Closes a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionClosePreparedStatementRequest\n"
+                 "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQuery object containing the SQL statement.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const ServerCallContext& context,
+                                        const StatementQuery& command,
+                                        const FlightDescriptor& descriptor,
+                                        std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQueryTicket containing the statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetStatement(const ServerCallContext& context,
+                                const StatementQueryTicket& command,
+                                std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for executing an already created prepared statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPreparedStatement(const ServerCallContext& context,
+                                                const PreparedStatementQuery& command,
+                                                const FlightDescriptor& descriptor,
+                                                std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the prepared statement query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetPreparedStatement(const ServerCallContext& context,
+                                        const PreparedStatementQuery& command,
+                                        std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for listing catalogs.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoCatalogs(const ServerCallContext& context,
+                                       const FlightDescriptor& descriptor,
+                                       std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of catalogs.
+  /// \param[in] context  Per-call context.
+  /// \param[out] result  An interface for sending data back to the client.
+  /// \return             Status.
+  virtual Status DoGetCatalogs(const ServerCallContext& context,
+                               std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for retrieving other information (See SqlInfo).
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetSqlInfo object containing the list of SqlInfo
+  ///                         to be returned.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                      const GetSqlInfo& command,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of SqlInfo results.
+  /// \param[in] context    Per-call context.
+  /// \param[in] command    The GetSqlInfo object containing the list of SqlInfo
+  ///                       to be returned.
+  /// \param[out] result    The FlightDataStream containing the results.
+  /// \return               Status.
+  virtual Status DoGetSqlInfo(const ServerCallContext& context, const GetSqlInfo& command,
+                              std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for listing schemas.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetSchemas object which may contain filters for
+  ///                         catalog and schema name.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoSchemas(const ServerCallContext& context,
+                                      const GetSchemas& command,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of schemas.
+  /// \param[in] context   Per-call context.
+  /// \param[in] command   The GetSchemas object which may contain filters for
+  ///                      catalog and schema name.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return              Status.
+  virtual Status DoGetSchemas(const ServerCallContext& context, const GetSchemas& command,
+                              std::unique_ptr<FlightDataStream>* result);
+
+  ///\brief Gets a FlightInfo for listing tables.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetTables object which may contain filters for
+  ///                         catalog, schema and table names.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoTables(const ServerCallContext& context,
+                                     const GetTables& command,
+                                     const FlightDescriptor& descriptor,
+                                     std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of tables.
+  /// \param[in] context   Per-call context.
+  /// \param[in] command   The GetTables object which may contain filters for
+  ///                      catalog, schema and table names.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return              Status.
+  virtual Status DoGetTables(const ServerCallContext& context, const GetTables& command,
+                             std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about the table types.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoTableTypes(const ServerCallContext& context,
+                                         const FlightDescriptor& descriptor,
+                                         std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the table types.
+  /// \param[in] context   Per-call context.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return               Status.
+  virtual Status DoGetTableTypes(const ServerCallContext& context,
+                                 std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about primary and foreign keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetPrimaryKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPrimaryKeys(const ServerCallContext& context,
+                                          const GetPrimaryKeys& command,
+                                          const FlightDescriptor& descriptor,
+                                          std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the primary and
+  /// foreign
+  ///        keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetPrimaryKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetPrimaryKeys(const ServerCallContext& context,
+                                  const GetPrimaryKeys& command,
+                                  std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetExportedKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoExportedKeys(const ServerCallContext& context,
+                                           const GetExportedKeys& command,
+                                           const FlightDescriptor& descriptor,
+                                           std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  /// primary
+  ///        keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetExportedKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetExportedKeys(const ServerCallContext& context,
+                                   const GetExportedKeys& command,
+                                   std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetImportedKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoImportedKeys(const ServerCallContext& context,
+                                           const GetImportedKeys& command,
+                                           const FlightDescriptor& descriptor,
+                                           std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  ///        primary keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetImportedKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetImportedKeys(const ServerCallContext& context,
+                                   const GetImportedKeys& command,
+                                   std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetCrossReference object with necessary
+  /// information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoCrossReference(const ServerCallContext& context,
+                                             const GetCrossReference& command,
+                                             const FlightDescriptor& descriptor,
+                                             std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  ///        primary keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetCrossReference object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetCrossReference(const ServerCallContext& context,
+                                     const GetCrossReference& command,
+                                     std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Executes an update SQL statement.
+  /// \param[in] context  The call context.
+  /// \param[in] command  The StatementUpdate object containing the SQL statement.
+  /// \param[in] reader   a sequence of uploaded record batches.
+  /// \return             The changed record count.
+  virtual arrow::Result<int64_t> DoPutCommandStatementUpdate(
+      const ServerCallContext& context, const StatementUpdate& command,
+      std::unique_ptr<FlightMessageReader>& reader);

Review comment:
       As per the coding style guide, mutable reference arguments should be avoided (either use a const-ref if it's immutable, or a non-const-pointer if it's mutable). This avoids ambiguities at call sites when a non-pointer is passed as argument.

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,177 @@
+// 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/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/builder.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                             \
+  case TYPE_CLASS##Type::type_id: {                                               \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                               \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);              \
+    if (string == nullptr) {                                                      \
+      ARROW_RETURN_NOT_OK(                                                        \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());        \
+      break;                                                                      \
+    }                                                                             \
+    ARROW_RETURN_NOT_OK(                                                          \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes)); \
+    break;                                                                        \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK(                                                             \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());             \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes)); \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                        \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);             \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \
+  }
+
+#define FLOAT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                      \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    double value = sqlite3_column_double(STMT, COLUMN);                   \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \
+  }
+
+#define MAX_BATCH_SIZE 1024
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<Schema> SqliteStatementBatchReader::schema() const { return schema_; }
+
+SqliteStatementBatchReader::SqliteStatementBatchReader(
+    std::shared_ptr<SqliteStatement> statement, std::shared_ptr<Schema> schema)
+    : statement_(std::move(statement)),
+      schema_(std::move(schema)),
+      rc_(SQLITE_OK),
+      already_executed_(false) {}
+
+Result<std::shared_ptr<SqliteStatementBatchReader>> SqliteStatementBatchReader::Create(
+    const std::shared_ptr<SqliteStatement>& statement_) {
+  int rc;
+  ARROW_RETURN_NOT_OK(statement_->Step(&rc));
+
+  std::shared_ptr<Schema> schema;
+  ARROW_RETURN_NOT_OK(statement_->GetSchema(&schema));
+
+  std::shared_ptr<SqliteStatementBatchReader> result(
+      new SqliteStatementBatchReader(statement_, schema));
+
+  return result;
+}
+
+arrow::Result<std::shared_ptr<SqliteStatementBatchReader>>
+SqliteStatementBatchReader::Create(const std::shared_ptr<SqliteStatement>& statement,
+                                   const std::shared_ptr<Schema>& schema) {
+  std::shared_ptr<SqliteStatementBatchReader> result(
+      new SqliteStatementBatchReader(statement, schema));
+
+  return result;
+}
+
+Status SqliteStatementBatchReader::ReadNext(std::shared_ptr<RecordBatch>* out) {
+  sqlite3_stmt* stmt_ = statement_->GetSqlite3Stmt();
+
+  const int num_fields = schema_->num_fields();
+  std::vector<std::unique_ptr<arrow::ArrayBuilder>> builders(num_fields);
+
+  for (int i = 0; i < num_fields; i++) {
+    const std::shared_ptr<Field>& field = schema_->field(i);
+    const std::shared_ptr<DataType>& field_type = field->type();
+
+    ARROW_RETURN_NOT_OK(MakeBuilder(default_memory_pool(), field_type, &builders[i]));
+  }
+
+  if (!already_executed_) {
+    ARROW_RETURN_NOT_OK(statement_->Reset(&rc_));
+    ARROW_RETURN_NOT_OK(statement_->Step(&rc_));
+    already_executed_ = true;
+  }
+
+  int rows = 0;
+  while (rows < MAX_BATCH_SIZE && rc_ == SQLITE_ROW) {
+    rows++;
+    for (int i = 0; i < num_fields; i++) {
+      const std::shared_ptr<Field>& field = schema_->field(i);
+      const std::shared_ptr<DataType>& field_type = field->type();
+      ArrayBuilder& builder = *builders[i];
+
+      switch (field_type->id()) {

Review comment:
       Note: if this were production code, it would be better to move the switch out of the inner loop. Also, we would probably presize the builders. As this is example code, it can probably stay as-is (but perhaps add a comment?).

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any, const SqlInfoResultMap& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =

Review comment:
       Same here. Can just write `auto buffer = ...`

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any, const SqlInfoResultMap& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::ListActions(const ServerCallContext& context,
+                                        std::vector<ActionType>* actions) {
+  *actions = {FlightSqlServerBase::kCreatePreparedStatementActionType,
+              FlightSqlServerBase::kClosePreparedStatementActionType};
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::DoAction(const ServerCallContext& context,
+                                     const Action& action,
+                                     std::unique_ptr<ResultStream>* result_stream) {
+  if (action.type == FlightSqlServerBase::kCreatePreparedStatementActionType.type) {
+    google::protobuf::Any any_command;
+    if (!any_command.ParseFromArray(action.body->data(),
+                                    static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionCreatePreparedStatementRequest internal_command,
+                          ParseActionCreatePreparedStatementRequest(any_command));
+    ARROW_ASSIGN_OR_RAISE(auto result, CreatePreparedStatement(context, internal_command))
+
+    pb::sql::ActionCreatePreparedStatementResult action_result;
+    action_result.set_prepared_statement_handle(result.prepared_statement_handle);
+    if (result.dataset_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_dataset_schema,
+                            ipc::SerializeSchema(*result.dataset_schema))
+      action_result.set_dataset_schema(serialized_dataset_schema->ToString());
+    }
+    if (result.parameter_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_parameter_schema,
+                            ipc::SerializeSchema(*result.parameter_schema))
+      action_result.set_parameter_schema(serialized_parameter_schema->ToString());
+    }
+
+    google::protobuf::Any any;
+    any.PackFrom(action_result);
+
+    auto buf = Buffer::FromString(any.SerializeAsString());
+    *result_stream = std::unique_ptr<ResultStream>(new SimpleResultStream({Result{buf}}));
+
+    return Status::OK();
+  } else if (action.type == FlightSqlServerBase::kClosePreparedStatementActionType.type) {
+    google::protobuf::Any any;
+    if (!any.ParseFromArray(action.body->data(), static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionClosePreparedStatementRequest internal_command,
+                          ParseActionClosePreparedStatementRequest(any));
+
+    return ClosePreparedStatement(context, internal_command, result_stream);
+  }
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCatalogs(const ServerCallContext& context,
+                                                  const FlightDescriptor& descriptor,
+                                                  std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCatalogs(const ServerCallContext& context,
+                                          std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoStatement(const ServerCallContext& context,
+                                                   const StatementQuery& command,
+                                                   const FlightDescriptor& descriptor,
+                                                   std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetStatement(const ServerCallContext& context,
+                                           const StatementQueryTicket& command,
+                                           std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                                 const GetSqlInfo& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  assert(info != nullptr);
+
+  if (sql_info_id_to_result_.empty()) {
+    return Status::NotImplemented("GetFlightInfoSqlInfo not implemented");

Review comment:
       This error message is a bit weird as other cases seem implemented below.

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any, const SqlInfoResultMap& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::ListActions(const ServerCallContext& context,
+                                        std::vector<ActionType>* actions) {
+  *actions = {FlightSqlServerBase::kCreatePreparedStatementActionType,
+              FlightSqlServerBase::kClosePreparedStatementActionType};
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::DoAction(const ServerCallContext& context,
+                                     const Action& action,
+                                     std::unique_ptr<ResultStream>* result_stream) {
+  if (action.type == FlightSqlServerBase::kCreatePreparedStatementActionType.type) {
+    google::protobuf::Any any_command;
+    if (!any_command.ParseFromArray(action.body->data(),
+                                    static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionCreatePreparedStatementRequest internal_command,
+                          ParseActionCreatePreparedStatementRequest(any_command));
+    ARROW_ASSIGN_OR_RAISE(auto result, CreatePreparedStatement(context, internal_command))
+
+    pb::sql::ActionCreatePreparedStatementResult action_result;
+    action_result.set_prepared_statement_handle(result.prepared_statement_handle);
+    if (result.dataset_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_dataset_schema,
+                            ipc::SerializeSchema(*result.dataset_schema))
+      action_result.set_dataset_schema(serialized_dataset_schema->ToString());
+    }
+    if (result.parameter_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_parameter_schema,
+                            ipc::SerializeSchema(*result.parameter_schema))
+      action_result.set_parameter_schema(serialized_parameter_schema->ToString());
+    }
+
+    google::protobuf::Any any;
+    any.PackFrom(action_result);
+
+    auto buf = Buffer::FromString(any.SerializeAsString());
+    *result_stream = std::unique_ptr<ResultStream>(new SimpleResultStream({Result{buf}}));
+
+    return Status::OK();
+  } else if (action.type == FlightSqlServerBase::kClosePreparedStatementActionType.type) {
+    google::protobuf::Any any;
+    if (!any.ParseFromArray(action.body->data(), static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionClosePreparedStatementRequest internal_command,
+                          ParseActionClosePreparedStatementRequest(any));
+
+    return ClosePreparedStatement(context, internal_command, result_stream);
+  }
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCatalogs(const ServerCallContext& context,
+                                                  const FlightDescriptor& descriptor,
+                                                  std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCatalogs(const ServerCallContext& context,
+                                          std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoStatement(const ServerCallContext& context,
+                                                   const StatementQuery& command,
+                                                   const FlightDescriptor& descriptor,
+                                                   std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetStatement(const ServerCallContext& context,
+                                           const StatementQueryTicket& command,
+                                           std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                                 const GetSqlInfo& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  assert(info != nullptr);

Review comment:
       Nit, but we usually rely on the `DCHECK` macros defined in `arrow/util/logging.h`, e.g. `DCHECK_NE(info, nullptr)`.

##########
File path: cpp/src/arrow/flight/sql/server.h
##########
@@ -0,0 +1,495 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/server.h"
+#include "arrow/flight/sql/server.h"
+#include "arrow/flight/sql/sql_info_types.h"
+#include "arrow/util/optional.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  std::vector<int32_t> info;
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;
+  util::optional<std::string> fk_catalog;
+  util::optional<std::string> fk_schema;
+  std::string fk_table;
+};
+
+struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+/// \brief A utility function to create a ticket for a statement query.
+///        Intended for Flight SQL server implementations.
+/// \param[in] statement_handle      The statement handle that will originate the ticket.
+/// \return                          The parsed ticket as an string.
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle);
+
+class ARROW_EXPORT FlightSqlServerBase : public FlightServerBase {
+ private:
+  SqlInfoResultMap sql_info_id_to_result_;
+
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType kCreatePreparedStatementActionType =
+      ActionType{"CreatePreparedStatement",
+                 "Creates a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionCreatePreparedStatementRequest\n"
+                 "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType kClosePreparedStatementActionType =
+      ActionType{"ClosePreparedStatement",
+                 "Closes a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionClosePreparedStatementRequest\n"
+                 "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQuery object containing the SQL statement.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const ServerCallContext& context,
+                                        const StatementQuery& command,
+                                        const FlightDescriptor& descriptor,
+                                        std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQueryTicket containing the statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetStatement(const ServerCallContext& context,
+                                const StatementQueryTicket& command,
+                                std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for executing an already created prepared statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPreparedStatement(const ServerCallContext& context,
+                                                const PreparedStatementQuery& command,
+                                                const FlightDescriptor& descriptor,
+                                                std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the prepared statement query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetPreparedStatement(const ServerCallContext& context,
+                                        const PreparedStatementQuery& command,
+                                        std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for listing catalogs.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoCatalogs(const ServerCallContext& context,
+                                       const FlightDescriptor& descriptor,
+                                       std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of catalogs.
+  /// \param[in] context  Per-call context.
+  /// \param[out] result  An interface for sending data back to the client.
+  /// \return             Status.
+  virtual Status DoGetCatalogs(const ServerCallContext& context,
+                               std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for retrieving other information (See SqlInfo).
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetSqlInfo object containing the list of SqlInfo
+  ///                         to be returned.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                      const GetSqlInfo& command,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of SqlInfo results.
+  /// \param[in] context    Per-call context.
+  /// \param[in] command    The GetSqlInfo object containing the list of SqlInfo
+  ///                       to be returned.
+  /// \param[out] result    The FlightDataStream containing the results.
+  /// \return               Status.
+  virtual Status DoGetSqlInfo(const ServerCallContext& context, const GetSqlInfo& command,
+                              std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for listing schemas.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetSchemas object which may contain filters for
+  ///                         catalog and schema name.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoSchemas(const ServerCallContext& context,
+                                      const GetSchemas& command,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of schemas.
+  /// \param[in] context   Per-call context.
+  /// \param[in] command   The GetSchemas object which may contain filters for
+  ///                      catalog and schema name.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return              Status.
+  virtual Status DoGetSchemas(const ServerCallContext& context, const GetSchemas& command,
+                              std::unique_ptr<FlightDataStream>* result);
+
+  ///\brief Gets a FlightInfo for listing tables.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetTables object which may contain filters for
+  ///                         catalog, schema and table names.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoTables(const ServerCallContext& context,
+                                     const GetTables& command,
+                                     const FlightDescriptor& descriptor,
+                                     std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of tables.
+  /// \param[in] context   Per-call context.
+  /// \param[in] command   The GetTables object which may contain filters for
+  ///                      catalog, schema and table names.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return              Status.
+  virtual Status DoGetTables(const ServerCallContext& context, const GetTables& command,
+                             std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about the table types.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoTableTypes(const ServerCallContext& context,
+                                         const FlightDescriptor& descriptor,
+                                         std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the table types.
+  /// \param[in] context   Per-call context.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return               Status.
+  virtual Status DoGetTableTypes(const ServerCallContext& context,
+                                 std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about primary and foreign keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetPrimaryKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPrimaryKeys(const ServerCallContext& context,
+                                          const GetPrimaryKeys& command,
+                                          const FlightDescriptor& descriptor,
+                                          std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the primary and
+  /// foreign
+  ///        keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetPrimaryKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetPrimaryKeys(const ServerCallContext& context,
+                                  const GetPrimaryKeys& command,
+                                  std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetExportedKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoExportedKeys(const ServerCallContext& context,
+                                           const GetExportedKeys& command,
+                                           const FlightDescriptor& descriptor,
+                                           std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  /// primary
+  ///        keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetExportedKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetExportedKeys(const ServerCallContext& context,
+                                   const GetExportedKeys& command,
+                                   std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetImportedKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoImportedKeys(const ServerCallContext& context,
+                                           const GetImportedKeys& command,
+                                           const FlightDescriptor& descriptor,
+                                           std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  ///        primary keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetImportedKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetImportedKeys(const ServerCallContext& context,
+                                   const GetImportedKeys& command,
+                                   std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetCrossReference object with necessary
+  /// information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoCrossReference(const ServerCallContext& context,
+                                             const GetCrossReference& command,
+                                             const FlightDescriptor& descriptor,
+                                             std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  ///        primary keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetCrossReference object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetCrossReference(const ServerCallContext& context,
+                                     const GetCrossReference& command,
+                                     std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Executes an update SQL statement.
+  /// \param[in] context  The call context.
+  /// \param[in] command  The StatementUpdate object containing the SQL statement.
+  /// \param[in] reader   a sequence of uploaded record batches.
+  /// \return             The changed record count.
+  virtual arrow::Result<int64_t> DoPutCommandStatementUpdate(
+      const ServerCallContext& context, const StatementUpdate& command,
+      std::unique_ptr<FlightMessageReader>& reader);
+
+  /// \brief Create a prepared statement from given SQL statement.
+  /// \param[in] context  The call context.
+  /// \param[in] request  The ActionCreatePreparedStatementRequest object containing the
+  ///                     SQL statement.
+  /// \return             A ActionCreatePreparedStatementResult containing the dataset
+  ///                     and parameter schemas and a handle for created statement.
+  virtual arrow::Result<ActionCreatePreparedStatementResult> CreatePreparedStatement(
+      const ServerCallContext& context,
+      const ActionCreatePreparedStatementRequest& request);
+
+  /// \brief Closes a prepared statement.
+  /// \param[in] context  The call context.
+  /// \param[in] request  The ActionClosePreparedStatementRequest object containing the
+  ///                     prepared statement handle.
+  /// \param[out] result  Empty ResultStream.
+  virtual Status ClosePreparedStatement(
+      const ServerCallContext& context,
+      const ActionClosePreparedStatementRequest& request,
+      std::unique_ptr<ResultStream>* result);
+
+  /// \brief Binds parameters to given prepared statement.
+  /// \param[in] context  The call context.
+  /// \param[in] command  The PreparedStatementQuery object containing the
+  ///                     prepared statement handle.
+  /// \param[in] reader   A sequence of uploaded record batches.
+  /// \param[in] writer   Send metadata back to the client.
+  virtual Status DoPutPreparedStatementQuery(const ServerCallContext& context,
+                                             const PreparedStatementQuery& command,
+                                             FlightMessageReader* reader,
+                                             FlightMetadataWriter* writer);
+
+  /// \brief Executes an update SQL prepared statement.
+  /// \param[in] context  The call context.
+  /// \param[in] command  The PreparedStatementUpdate object containing the
+  ///                     prepared statement handle.
+  /// \param[in] reader   a sequence of uploaded record batches.
+  /// \return             The changed record count.
+  virtual arrow::Result<int64_t> DoPutPreparedStatementUpdate(
+      const ServerCallContext& context, const PreparedStatementUpdate& command,
+      FlightMessageReader* reader);
+
+  /// \brief Registers a new SqlInfo result.

Review comment:
       Hmm, what does "Register" mean here?

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_server.h
##########
@@ -0,0 +1,357 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "arrow/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+#include "arrow/flight/sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+namespace flight_sql_pb = arrow::flight::protocol::sql;
+
+/// \brief Gets the mapping from SQL info ids to SqlInfoResult instances.
+/// \return the cache.
+inline SqlInfoResultMap GetSqlInfoResultMap() {

Review comment:
       Does this result need to be defined in a `.h`? I know it's an example, but it should still promote good modularization practices, IMHO.

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -0,0 +1,783 @@
+// 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.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "arrow/api.h"

Review comment:
       Should avoid including `arrow/api.h` as that's very heavy to include. Instead, include the desired specific headers.

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -0,0 +1,783 @@
+// 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.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/api.h"
+#include "arrow/flight/sql/example/sqlite_server.h"
+#include "arrow/flight/test_util.h"
+#include "arrow/flight/types.h"
+#include "arrow/testing/gtest_util.h"
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+/// \brief Auxiliary variant visitor used to assert that GetSqlInfo's values are
+/// correctly placed on its DenseUnionArray
+class SqlInfoDenseUnionValidator {
+ private:
+  const DenseUnionScalar& data;
+
+ public:
+  /// \brief Asserts that the current DenseUnionScalar equals to given string value
+  void operator()(const std::string& string_value) const {
+    const auto& scalar = dynamic_cast<const StringScalar&>(*data.value);
+    ASSERT_EQ(string_value, scalar.ToString());
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given bool value
+  void operator()(const bool bool_value) const {
+    const auto& scalar = dynamic_cast<const BooleanScalar&>(*data.value);
+    ASSERT_EQ(bool_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int64_t value
+  void operator()(const int64_t bigint_value) const {
+    const auto& scalar = dynamic_cast<const Int64Scalar&>(*data.value);
+    ASSERT_EQ(bigint_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32_t value
+  void operator()(const int32_t int32_bitmask) const {
+    const auto& scalar = dynamic_cast<const Int32Scalar&>(*data.value);
+    ASSERT_EQ(int32_bitmask, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given string list
+  void operator()(const std::vector<std::string>& string_list) const {
+    const auto& array = dynamic_cast<const StringArray&>(
+        *(dynamic_cast<const ListScalar&>(*data.value).value));
+
+    ASSERT_EQ(string_list.size(), array.length());
+
+    for (size_t index = 0; index < string_list.size(); index++) {
+      ASSERT_EQ(string_list[index], array.GetString(index));
+    }
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32 to int32 list
+  /// map.
+  void operator()(const std::unordered_map<int32_t, std::vector<int32_t>>&
+                      int32_to_int32_list) const {
+    const auto& struct_array = dynamic_cast<const StructArray&>(
+        *dynamic_cast<const MapScalar&>(*data.value).value);
+    const auto& keys = dynamic_cast<const Int32Array&>(*struct_array.field(0));
+    const auto& values = dynamic_cast<const ListArray&>(*struct_array.field(1));
+
+    // Assert that the given map has the right size
+    ASSERT_EQ(int32_to_int32_list.size(), keys.length());
+
+    // For each element on given MapScalar, assert it matches the argument
+    for (int i = 0; i < keys.length(); i++) {
+      ASSERT_OK_AND_ASSIGN(const auto& key_scalar, keys.GetScalar(i));
+      int32_t sql_info_id = dynamic_cast<const Int32Scalar&>(*key_scalar).value;
+
+      // Assert the key (SqlInfo id) exists
+      ASSERT_TRUE(int32_to_int32_list.count(sql_info_id));
+
+      const std::vector<int32_t>& expected_int32_list =
+          int32_to_int32_list.at(sql_info_id);
+
+      // Assert the value (int32 list) has the correct size
+      ASSERT_EQ(expected_int32_list.size(), values.value_length(i));
+
+      // For each element on current ListScalar, assert it matches with the argument
+      for (size_t j = 0; j < expected_int32_list.size(); j++) {
+        ASSERT_OK_AND_ASSIGN(auto list_item_scalar,
+                             values.values()->GetScalar(values.value_offset(i) + j));
+        const auto& list_item = dynamic_cast<const Int32Scalar&>(*list_item_scalar).value;
+        ASSERT_EQ(expected_int32_list[j], list_item);
+      }
+    }
+  }
+
+  explicit SqlInfoDenseUnionValidator(const DenseUnionScalar& data) : data(data) {}
+
+  SqlInfoDenseUnionValidator(const SqlInfoDenseUnionValidator&) = delete;
+  SqlInfoDenseUnionValidator(SqlInfoDenseUnionValidator&&) = delete;
+  SqlInfoDenseUnionValidator& operator=(const SqlInfoDenseUnionValidator&) = delete;
+};
+
+std::unique_ptr<TestServer> server;
+std::unique_ptr<FlightSqlClient> sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server.reset(new TestServer("flight_sql_test_server"));
+    server->Start();
+    for (int i = 0; i < 100; i++) {
+      std::this_thread::sleep_for(std::chrono::milliseconds(10));
+      if (server->IsRunning()) {
+        break;
+      }
+    }
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+    server->Stop();
+    server.reset();
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array;
+  std::shared_ptr<Array> keyname_array;
+  std::shared_ptr<Array> value_array;
+  std::shared_ptr<Array> foreignId_array;
+  ArrayFromVector<Int64Type>({1, 2, 3}, &id_array);
+  ArrayFromVector<StringType, std::string>({"one", "zero", "negative one"},
+                                           &keyname_array);
+  ArrayFromVector<Int64Type>({1, 0, -1}, &value_array);
+  ArrayFromVector<Int64Type>({1, 1, 1}, &foreignId_array);

Review comment:
       It's simpler and more readable to use the `ArrayFromJSON` facility, e.g.:
   ```c++
   auto id_array = ArrayFromJSON(int64(), "[1, 2, 3]");
   auto keyname_array = ArrayFromJSON(utf8(), R"(["one", "zero", "negative one"])");
   ```
   
   (there's even a `TableFromJSON` if you want)
   

##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, const std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  /// \brief Retrieve the FlightInfo.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] descriptor   The flight descriptior.
+  /// \param[out] info        The flight info with the metadata.
+  /// \return Status.
+  // NOTE: This is public because it is been used by the anonymous
+  // function GetFlightInfoForCommand.
+  virtual Status GetFlightInfo(const FlightCallOptions& options,
+                               const FlightDescriptor& descriptor,
+                               std::unique_ptr<FlightInfo>* info) {
+    return impl_->GetFlightInfo(options, descriptor, info);
+  }
+
+ protected:
+  virtual Status DoPut(const FlightCallOptions& options,
+                       const FlightDescriptor& descriptor,
+                       const std::shared_ptr<Schema>& schema,
+                       std::unique_ptr<FlightStreamWriter>* stream,
+                       std::unique_ptr<FlightMetadataReader>* reader) {
+    return impl_->DoPut(options, descriptor, schema, stream, reader);
+  }
+
+  virtual Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+                       std::unique_ptr<FlightStreamReader>* stream) {
+    return impl_->DoGet(options, ticket, stream);
+  }
+
+  virtual Status DoAction(const FlightCallOptions& options, const Action& action,
+                          std::unique_ptr<ResultStream>* results) {
+    return impl_->DoAction(options, action, results);
+  }
+};
+
+/// \brief PreparedStatement class from flight sql.
+class ARROW_EXPORT PreparedStatement {
+  FlightSqlClient* client_;
+  FlightCallOptions options_;
+  std::string handle_;
+  std::shared_ptr<Schema> dataset_schema_;
+  std::shared_ptr<Schema> parameter_schema_;
+  std::shared_ptr<RecordBatch> parameter_binding_;
+  bool is_closed_;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client                Client object used to make the RPC requests.
+  /// \param[in] handle                Handle for this prepared statement.
+  /// \param[in] dataset_schema        Schema of the resulting dataset.
+  /// \param[in] parameter_schema      Schema of the parameters (if any).
+  /// \param[in] options               RPC-layer hints for this call.
+  PreparedStatement(FlightSqlClient* client, std::string handle,
+                    std::shared_ptr<Schema> dataset_schema,
+                    std::shared_ptr<Schema> parameter_schema, FlightCallOptions options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  /// NOTE: It is best to explicitly close the PreparedStatement, otherwise
+  /// errors can't be caught.
+  ~PreparedStatement();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \return A FlightInfo object representing the stream(s) to fetch.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute();
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \return The number of rows affected.
+  arrow::Result<int64_t> ExecuteUpdate();
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \return The parameter schema from the query.
+  std::shared_ptr<Schema> parameter_schema() const;
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \return The ResultSet schema from the query.
+  std::shared_ptr<Schema> dataset_schema() const;
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.

Review comment:
       Also, this should explain what "closing" means.

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,177 @@
+// 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/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/builder.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                             \
+  case TYPE_CLASS##Type::type_id: {                                               \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                               \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);              \
+    if (string == nullptr) {                                                      \
+      ARROW_RETURN_NOT_OK(                                                        \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());        \
+      break;                                                                      \
+    }                                                                             \
+    ARROW_RETURN_NOT_OK(                                                          \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes)); \
+    break;                                                                        \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK(                                                             \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());             \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes)); \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                        \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);             \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \
+  }
+
+#define FLOAT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                      \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    double value = sqlite3_column_double(STMT, COLUMN);                   \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \

Review comment:
       Same question here.

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any, const SqlInfoResultMap& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::ListActions(const ServerCallContext& context,
+                                        std::vector<ActionType>* actions) {
+  *actions = {FlightSqlServerBase::kCreatePreparedStatementActionType,
+              FlightSqlServerBase::kClosePreparedStatementActionType};
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::DoAction(const ServerCallContext& context,
+                                     const Action& action,
+                                     std::unique_ptr<ResultStream>* result_stream) {
+  if (action.type == FlightSqlServerBase::kCreatePreparedStatementActionType.type) {
+    google::protobuf::Any any_command;
+    if (!any_command.ParseFromArray(action.body->data(),
+                                    static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionCreatePreparedStatementRequest internal_command,
+                          ParseActionCreatePreparedStatementRequest(any_command));
+    ARROW_ASSIGN_OR_RAISE(auto result, CreatePreparedStatement(context, internal_command))
+
+    pb::sql::ActionCreatePreparedStatementResult action_result;
+    action_result.set_prepared_statement_handle(result.prepared_statement_handle);
+    if (result.dataset_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_dataset_schema,
+                            ipc::SerializeSchema(*result.dataset_schema))
+      action_result.set_dataset_schema(serialized_dataset_schema->ToString());
+    }
+    if (result.parameter_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_parameter_schema,
+                            ipc::SerializeSchema(*result.parameter_schema))
+      action_result.set_parameter_schema(serialized_parameter_schema->ToString());
+    }
+
+    google::protobuf::Any any;
+    any.PackFrom(action_result);
+
+    auto buf = Buffer::FromString(any.SerializeAsString());
+    *result_stream = std::unique_ptr<ResultStream>(new SimpleResultStream({Result{buf}}));
+
+    return Status::OK();
+  } else if (action.type == FlightSqlServerBase::kClosePreparedStatementActionType.type) {
+    google::protobuf::Any any;
+    if (!any.ParseFromArray(action.body->data(), static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionClosePreparedStatementRequest internal_command,
+                          ParseActionClosePreparedStatementRequest(any));
+
+    return ClosePreparedStatement(context, internal_command, result_stream);
+  }
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCatalogs(const ServerCallContext& context,
+                                                  const FlightDescriptor& descriptor,
+                                                  std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCatalogs(const ServerCallContext& context,
+                                          std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoStatement(const ServerCallContext& context,
+                                                   const StatementQuery& command,
+                                                   const FlightDescriptor& descriptor,
+                                                   std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetStatement(const ServerCallContext& context,
+                                           const StatementQueryTicket& command,
+                                           std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                                 const GetSqlInfo& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  assert(info != nullptr);
+
+  if (sql_info_id_to_result_.empty()) {
+    return Status::NotImplemented("GetFlightInfoSqlInfo not implemented");
+  }
+
+  std::vector<FlightEndpoint> endpoints{FlightEndpoint{{descriptor.cmd}, {}}};
+  ARROW_ASSIGN_OR_RAISE(auto result, FlightInfo::Make(*SqlSchema::GetSqlInfoSchema(),
+                                                      descriptor, endpoints, -1, -1))
+
+  *info = std::unique_ptr<FlightInfo>(new FlightInfo(result));
+
+  return Status::OK();
+}
+
+void FlightSqlServerBase::RegisterSqlInfo(int32_t id, const SqlInfoResult& result) {
+  sql_info_id_to_result_[id] = result;
+}
+
+Status FlightSqlServerBase::DoGetSqlInfo(const ServerCallContext& context,
+                                         const GetSqlInfo& command,
+                                         std::unique_ptr<FlightDataStream>* result) {
+  DCHECK(result);
+
+  MemoryPool* memory_pool = default_memory_pool();
+  UInt32Builder name_field_builder(memory_pool);
+  std::unique_ptr<ArrayBuilder> value_field_builder;
+  const auto& value_field_type = std::static_pointer_cast<DenseUnionType>(
+      SqlSchema::GetSqlInfoSchema()->fields()[1]->type());
+  ARROW_RETURN_NOT_OK(MakeBuilder(memory_pool, value_field_type, &value_field_builder));
+
+  internal::SqlInfoResultAppender sql_info_result_appender(
+      reinterpret_cast<DenseUnionBuilder&>(*value_field_builder));
+
+  // Populate both name_field_builder and value_field_builder for each element
+  // on command.info.
+  // value_field_builder is populated differently depending on the data type (as it is
+  // a DenseUnionBuilder). The population for each data type is implemented on
+  // internal::SqlInfoResultAppender.
+  for (const auto& info : command.info) {
+    if (!sql_info_id_to_result_.count(info)) {
+      return Status::KeyError(
+          "Attempt to fetch unregistered/unsupported SqlInfo option: " +
+          std::to_string(info));
+    }
+    ARROW_RETURN_NOT_OK(name_field_builder.Append(info));
+    ARROW_RETURN_NOT_OK(
+        arrow::util::visit(sql_info_result_appender, sql_info_id_to_result_.at(info)));

Review comment:
       Also, this should be tested if not already done.

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -0,0 +1,783 @@
+// 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.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/api.h"
+#include "arrow/flight/sql/example/sqlite_server.h"
+#include "arrow/flight/test_util.h"
+#include "arrow/flight/types.h"
+#include "arrow/testing/gtest_util.h"
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+/// \brief Auxiliary variant visitor used to assert that GetSqlInfo's values are
+/// correctly placed on its DenseUnionArray
+class SqlInfoDenseUnionValidator {
+ private:
+  const DenseUnionScalar& data;
+
+ public:
+  /// \brief Asserts that the current DenseUnionScalar equals to given string value
+  void operator()(const std::string& string_value) const {
+    const auto& scalar = dynamic_cast<const StringScalar&>(*data.value);
+    ASSERT_EQ(string_value, scalar.ToString());
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given bool value
+  void operator()(const bool bool_value) const {
+    const auto& scalar = dynamic_cast<const BooleanScalar&>(*data.value);
+    ASSERT_EQ(bool_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int64_t value
+  void operator()(const int64_t bigint_value) const {
+    const auto& scalar = dynamic_cast<const Int64Scalar&>(*data.value);
+    ASSERT_EQ(bigint_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32_t value
+  void operator()(const int32_t int32_bitmask) const {
+    const auto& scalar = dynamic_cast<const Int32Scalar&>(*data.value);
+    ASSERT_EQ(int32_bitmask, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given string list
+  void operator()(const std::vector<std::string>& string_list) const {
+    const auto& array = dynamic_cast<const StringArray&>(
+        *(dynamic_cast<const ListScalar&>(*data.value).value));
+
+    ASSERT_EQ(string_list.size(), array.length());
+
+    for (size_t index = 0; index < string_list.size(); index++) {
+      ASSERT_EQ(string_list[index], array.GetString(index));
+    }
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32 to int32 list
+  /// map.
+  void operator()(const std::unordered_map<int32_t, std::vector<int32_t>>&
+                      int32_to_int32_list) const {
+    const auto& struct_array = dynamic_cast<const StructArray&>(
+        *dynamic_cast<const MapScalar&>(*data.value).value);
+    const auto& keys = dynamic_cast<const Int32Array&>(*struct_array.field(0));
+    const auto& values = dynamic_cast<const ListArray&>(*struct_array.field(1));
+
+    // Assert that the given map has the right size
+    ASSERT_EQ(int32_to_int32_list.size(), keys.length());
+
+    // For each element on given MapScalar, assert it matches the argument
+    for (int i = 0; i < keys.length(); i++) {
+      ASSERT_OK_AND_ASSIGN(const auto& key_scalar, keys.GetScalar(i));
+      int32_t sql_info_id = dynamic_cast<const Int32Scalar&>(*key_scalar).value;
+
+      // Assert the key (SqlInfo id) exists
+      ASSERT_TRUE(int32_to_int32_list.count(sql_info_id));
+
+      const std::vector<int32_t>& expected_int32_list =
+          int32_to_int32_list.at(sql_info_id);
+
+      // Assert the value (int32 list) has the correct size
+      ASSERT_EQ(expected_int32_list.size(), values.value_length(i));
+
+      // For each element on current ListScalar, assert it matches with the argument
+      for (size_t j = 0; j < expected_int32_list.size(); j++) {
+        ASSERT_OK_AND_ASSIGN(auto list_item_scalar,
+                             values.values()->GetScalar(values.value_offset(i) + j));
+        const auto& list_item = dynamic_cast<const Int32Scalar&>(*list_item_scalar).value;
+        ASSERT_EQ(expected_int32_list[j], list_item);
+      }
+    }
+  }
+
+  explicit SqlInfoDenseUnionValidator(const DenseUnionScalar& data) : data(data) {}
+
+  SqlInfoDenseUnionValidator(const SqlInfoDenseUnionValidator&) = delete;
+  SqlInfoDenseUnionValidator(SqlInfoDenseUnionValidator&&) = delete;
+  SqlInfoDenseUnionValidator& operator=(const SqlInfoDenseUnionValidator&) = delete;
+};
+
+std::unique_ptr<TestServer> server;
+std::unique_ptr<FlightSqlClient> sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server.reset(new TestServer("flight_sql_test_server"));
+    server->Start();
+    for (int i = 0; i < 100; i++) {
+      std::this_thread::sleep_for(std::chrono::milliseconds(10));
+      if (server->IsRunning()) {
+        break;
+      }
+    }
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+    server->Stop();
+    server.reset();
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array;
+  std::shared_ptr<Array> keyname_array;
+  std::shared_ptr<Array> value_array;
+  std::shared_ptr<Array> foreignId_array;
+  ArrayFromVector<Int64Type>({1, 2, 3}, &id_array);
+  ArrayFromVector<StringType, std::string>({"one", "zero", "negative one"},
+                                           &keyname_array);
+  ArrayFromVector<Int64Type>({1, 0, -1}, &value_array);
+  ArrayFromVector<Int64Type>({1, 1, 1}, &foreignId_array);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::vector<std::string> table_types;
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {"foreignTable", "intTable", "sqlite_sequence"}, &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableFilter) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableTypesFilter) {
+  std::vector<std::string> table_types{"index"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_TRUE(table->schema()->Equals(SqlSchema::GetTablesSchema()));
+
+  ASSERT_EQ(table->num_rows(), 0);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithUnexistenceTableTypeFilter) {
+  std::vector<std::string> table_types{"table"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {
+          "foreignTable",
+          "intTable",
+          "sqlite_sequence",
+      },
+      &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithIncludedSchemas) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             true, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Schema> schema_table = arrow::schema(
+      {arrow::field("id", int64(), true), arrow::field("keyName", utf8(), true),
+       arrow::field("value", int64(), true), arrow::field("foreignId", int64(), true)});
+
+  const arrow::Result<std::shared_ptr<Buffer>>& value =
+      ipc::SerializeSchema(*schema_table);
+  std::shared_ptr<Buffer> schema_buffer;
+
+  ASSERT_OK_AND_ASSIGN(schema_buffer, value);

Review comment:
       Why don't you directly write `ASSERT_OK_AND_ASSIGN(auto schema_buffer, ipc::SerializeSchema(*schema_table));`?

##########
File path: cpp/src/arrow/flight/sql/client_test.cc
##########
@@ -0,0 +1,489 @@
+// 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/client.h"
+
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/api.h"
+#include "arrow/testing/gtest_util.h"
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlClientMock : public FlightSqlClient {
+ public:
+  FlightSqlClientMock() : FlightSqlClient(nullptr) {}
+
+  ~FlightSqlClientMock() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+class TestFlightSqlClient : public ::testing::Test {
+ protected:
+  FlightSqlClientMock sql_client;
+  FlightCallOptions call_options;

Review comment:
       `sql_client_`, `call_options_`

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -0,0 +1,783 @@
+// 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.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/api.h"
+#include "arrow/flight/sql/example/sqlite_server.h"
+#include "arrow/flight/test_util.h"
+#include "arrow/flight/types.h"
+#include "arrow/testing/gtest_util.h"
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+/// \brief Auxiliary variant visitor used to assert that GetSqlInfo's values are
+/// correctly placed on its DenseUnionArray
+class SqlInfoDenseUnionValidator {
+ private:
+  const DenseUnionScalar& data;
+
+ public:
+  /// \brief Asserts that the current DenseUnionScalar equals to given string value
+  void operator()(const std::string& string_value) const {
+    const auto& scalar = dynamic_cast<const StringScalar&>(*data.value);
+    ASSERT_EQ(string_value, scalar.ToString());
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given bool value
+  void operator()(const bool bool_value) const {
+    const auto& scalar = dynamic_cast<const BooleanScalar&>(*data.value);
+    ASSERT_EQ(bool_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int64_t value
+  void operator()(const int64_t bigint_value) const {
+    const auto& scalar = dynamic_cast<const Int64Scalar&>(*data.value);
+    ASSERT_EQ(bigint_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32_t value
+  void operator()(const int32_t int32_bitmask) const {
+    const auto& scalar = dynamic_cast<const Int32Scalar&>(*data.value);
+    ASSERT_EQ(int32_bitmask, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given string list
+  void operator()(const std::vector<std::string>& string_list) const {
+    const auto& array = dynamic_cast<const StringArray&>(
+        *(dynamic_cast<const ListScalar&>(*data.value).value));
+
+    ASSERT_EQ(string_list.size(), array.length());
+
+    for (size_t index = 0; index < string_list.size(); index++) {
+      ASSERT_EQ(string_list[index], array.GetString(index));
+    }
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32 to int32 list
+  /// map.
+  void operator()(const std::unordered_map<int32_t, std::vector<int32_t>>&
+                      int32_to_int32_list) const {
+    const auto& struct_array = dynamic_cast<const StructArray&>(
+        *dynamic_cast<const MapScalar&>(*data.value).value);
+    const auto& keys = dynamic_cast<const Int32Array&>(*struct_array.field(0));
+    const auto& values = dynamic_cast<const ListArray&>(*struct_array.field(1));
+
+    // Assert that the given map has the right size
+    ASSERT_EQ(int32_to_int32_list.size(), keys.length());
+
+    // For each element on given MapScalar, assert it matches the argument
+    for (int i = 0; i < keys.length(); i++) {
+      ASSERT_OK_AND_ASSIGN(const auto& key_scalar, keys.GetScalar(i));
+      int32_t sql_info_id = dynamic_cast<const Int32Scalar&>(*key_scalar).value;
+
+      // Assert the key (SqlInfo id) exists
+      ASSERT_TRUE(int32_to_int32_list.count(sql_info_id));
+
+      const std::vector<int32_t>& expected_int32_list =
+          int32_to_int32_list.at(sql_info_id);
+
+      // Assert the value (int32 list) has the correct size
+      ASSERT_EQ(expected_int32_list.size(), values.value_length(i));
+
+      // For each element on current ListScalar, assert it matches with the argument
+      for (size_t j = 0; j < expected_int32_list.size(); j++) {
+        ASSERT_OK_AND_ASSIGN(auto list_item_scalar,
+                             values.values()->GetScalar(values.value_offset(i) + j));
+        const auto& list_item = dynamic_cast<const Int32Scalar&>(*list_item_scalar).value;
+        ASSERT_EQ(expected_int32_list[j], list_item);
+      }
+    }
+  }
+
+  explicit SqlInfoDenseUnionValidator(const DenseUnionScalar& data) : data(data) {}
+
+  SqlInfoDenseUnionValidator(const SqlInfoDenseUnionValidator&) = delete;
+  SqlInfoDenseUnionValidator(SqlInfoDenseUnionValidator&&) = delete;
+  SqlInfoDenseUnionValidator& operator=(const SqlInfoDenseUnionValidator&) = delete;
+};
+
+std::unique_ptr<TestServer> server;
+std::unique_ptr<FlightSqlClient> sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server.reset(new TestServer("flight_sql_test_server"));
+    server->Start();
+    for (int i = 0; i < 100; i++) {
+      std::this_thread::sleep_for(std::chrono::milliseconds(10));
+      if (server->IsRunning()) {
+        break;
+      }
+    }
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+    server->Stop();
+    server.reset();
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array;
+  std::shared_ptr<Array> keyname_array;
+  std::shared_ptr<Array> value_array;
+  std::shared_ptr<Array> foreignId_array;
+  ArrayFromVector<Int64Type>({1, 2, 3}, &id_array);
+  ArrayFromVector<StringType, std::string>({"one", "zero", "negative one"},
+                                           &keyname_array);
+  ArrayFromVector<Int64Type>({1, 0, -1}, &value_array);
+  ArrayFromVector<Int64Type>({1, 1, 1}, &foreignId_array);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::vector<std::string> table_types;
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {"foreignTable", "intTable", "sqlite_sequence"}, &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableFilter) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableTypesFilter) {
+  std::vector<std::string> table_types{"index"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_TRUE(table->schema()->Equals(SqlSchema::GetTablesSchema()));
+
+  ASSERT_EQ(table->num_rows(), 0);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithUnexistenceTableTypeFilter) {
+  std::vector<std::string> table_types{"table"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {
+          "foreignTable",
+          "intTable",
+          "sqlite_sequence",
+      },
+      &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithIncludedSchemas) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             true, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Schema> schema_table = arrow::schema(
+      {arrow::field("id", int64(), true), arrow::field("keyName", utf8(), true),
+       arrow::field("value", int64(), true), arrow::field("foreignId", int64(), true)});
+
+  const arrow::Result<std::shared_ptr<Buffer>>& value =
+      ipc::SerializeSchema(*schema_table);
+  std::shared_ptr<Buffer> schema_buffer;
+
+  ASSERT_OK_AND_ASSIGN(schema_buffer, value);
+  std::shared_ptr<Array> table_schema;
+
+  ArrayFromVector<BinaryType, std::string>({schema_buffer->ToString()}, &table_schema);
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetTablesSchemaWithIncludedSchema(),
+                  {catalog_name, schema_name, table_name, table_type, table_schema});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetCatalogs) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetCatalogs({}));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema = SqlSchema::GetCatalogsSchema();
+
+  ASSERT_TRUE(table->schema()->Equals(*expected_schema));
+  ASSERT_EQ(0, table->num_rows());
+}
+
+TEST(TestFlightSqlServer, TestCommandGetSchemas) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetSchemas({}, NULLPTR, NULLPTR));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema = SqlSchema::GetSchemasSchema();
+
+  ASSERT_TRUE(table->schema()->Equals(*expected_schema));
+  ASSERT_EQ(0, table->num_rows());
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTableTypes) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetTableTypes({}));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetTableTypesSchema(), {table_type});
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandStatementUpdate) {
+  int64_t result;
+  ASSERT_OK_AND_ASSIGN(result,
+                       sql_client->ExecuteUpdate(
+                           {},
+                           "INSERT INTO intTable (keyName, value) VALUES "
+                           "('KEYNAME1', 1001), ('KEYNAME2', 1002), ('KEYNAME3', 1003)"));
+  ASSERT_EQ(3, result);

Review comment:
       More simply:
   ```c++
   ASSERT_OK_AND_EQ(3, sql_client->ExecuteUpdate(...));
   ```

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,177 @@
+// 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/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/builder.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                             \
+  case TYPE_CLASS##Type::type_id: {                                               \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                               \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);              \
+    if (string == nullptr) {                                                      \
+      ARROW_RETURN_NOT_OK(                                                        \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());        \
+      break;                                                                      \
+    }                                                                             \
+    ARROW_RETURN_NOT_OK(                                                          \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes)); \
+    break;                                                                        \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK(                                                             \
+          (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).AppendNull());             \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes)); \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                        \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);             \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \
+  }
+
+#define FLOAT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                      \
+  case TYPE_CLASS##Type::type_id: {                                       \
+    double value = sqlite3_column_double(STMT, COLUMN);                   \
+    ARROW_RETURN_NOT_OK(                                                  \
+        (reinterpret_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                \
+  }
+
+#define MAX_BATCH_SIZE 1024
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<Schema> SqliteStatementBatchReader::schema() const { return schema_; }
+
+SqliteStatementBatchReader::SqliteStatementBatchReader(
+    std::shared_ptr<SqliteStatement> statement, std::shared_ptr<Schema> schema)
+    : statement_(std::move(statement)),
+      schema_(std::move(schema)),
+      rc_(SQLITE_OK),
+      already_executed_(false) {}
+
+Result<std::shared_ptr<SqliteStatementBatchReader>> SqliteStatementBatchReader::Create(
+    const std::shared_ptr<SqliteStatement>& statement_) {
+  int rc;
+  ARROW_RETURN_NOT_OK(statement_->Step(&rc));
+
+  std::shared_ptr<Schema> schema;
+  ARROW_RETURN_NOT_OK(statement_->GetSchema(&schema));
+
+  std::shared_ptr<SqliteStatementBatchReader> result(
+      new SqliteStatementBatchReader(statement_, schema));
+
+  return result;
+}
+
+arrow::Result<std::shared_ptr<SqliteStatementBatchReader>>
+SqliteStatementBatchReader::Create(const std::shared_ptr<SqliteStatement>& statement,
+                                   const std::shared_ptr<Schema>& schema) {
+  std::shared_ptr<SqliteStatementBatchReader> result(
+      new SqliteStatementBatchReader(statement, schema));
+
+  return result;
+}
+
+Status SqliteStatementBatchReader::ReadNext(std::shared_ptr<RecordBatch>* out) {
+  sqlite3_stmt* stmt_ = statement_->GetSqlite3Stmt();
+
+  const int num_fields = schema_->num_fields();
+  std::vector<std::unique_ptr<arrow::ArrayBuilder>> builders(num_fields);
+
+  for (int i = 0; i < num_fields; i++) {
+    const std::shared_ptr<Field>& field = schema_->field(i);
+    const std::shared_ptr<DataType>& field_type = field->type();
+
+    ARROW_RETURN_NOT_OK(MakeBuilder(default_memory_pool(), field_type, &builders[i]));
+  }
+
+  if (!already_executed_) {
+    ARROW_RETURN_NOT_OK(statement_->Reset(&rc_));
+    ARROW_RETURN_NOT_OK(statement_->Step(&rc_));
+    already_executed_ = true;
+  }
+
+  int rows = 0;

Review comment:
       Should use `int64_t` probably.

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -0,0 +1,783 @@
+// 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.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/api.h"
+#include "arrow/flight/sql/example/sqlite_server.h"
+#include "arrow/flight/test_util.h"
+#include "arrow/flight/types.h"
+#include "arrow/testing/gtest_util.h"
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+/// \brief Auxiliary variant visitor used to assert that GetSqlInfo's values are
+/// correctly placed on its DenseUnionArray
+class SqlInfoDenseUnionValidator {
+ private:
+  const DenseUnionScalar& data;
+
+ public:
+  /// \brief Asserts that the current DenseUnionScalar equals to given string value
+  void operator()(const std::string& string_value) const {
+    const auto& scalar = dynamic_cast<const StringScalar&>(*data.value);
+    ASSERT_EQ(string_value, scalar.ToString());
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given bool value
+  void operator()(const bool bool_value) const {
+    const auto& scalar = dynamic_cast<const BooleanScalar&>(*data.value);
+    ASSERT_EQ(bool_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int64_t value
+  void operator()(const int64_t bigint_value) const {
+    const auto& scalar = dynamic_cast<const Int64Scalar&>(*data.value);
+    ASSERT_EQ(bigint_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32_t value
+  void operator()(const int32_t int32_bitmask) const {
+    const auto& scalar = dynamic_cast<const Int32Scalar&>(*data.value);
+    ASSERT_EQ(int32_bitmask, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given string list
+  void operator()(const std::vector<std::string>& string_list) const {
+    const auto& array = dynamic_cast<const StringArray&>(
+        *(dynamic_cast<const ListScalar&>(*data.value).value));
+
+    ASSERT_EQ(string_list.size(), array.length());
+
+    for (size_t index = 0; index < string_list.size(); index++) {
+      ASSERT_EQ(string_list[index], array.GetString(index));
+    }
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32 to int32 list
+  /// map.
+  void operator()(const std::unordered_map<int32_t, std::vector<int32_t>>&
+                      int32_to_int32_list) const {
+    const auto& struct_array = dynamic_cast<const StructArray&>(
+        *dynamic_cast<const MapScalar&>(*data.value).value);
+    const auto& keys = dynamic_cast<const Int32Array&>(*struct_array.field(0));
+    const auto& values = dynamic_cast<const ListArray&>(*struct_array.field(1));
+
+    // Assert that the given map has the right size
+    ASSERT_EQ(int32_to_int32_list.size(), keys.length());
+
+    // For each element on given MapScalar, assert it matches the argument
+    for (int i = 0; i < keys.length(); i++) {
+      ASSERT_OK_AND_ASSIGN(const auto& key_scalar, keys.GetScalar(i));
+      int32_t sql_info_id = dynamic_cast<const Int32Scalar&>(*key_scalar).value;
+
+      // Assert the key (SqlInfo id) exists
+      ASSERT_TRUE(int32_to_int32_list.count(sql_info_id));
+
+      const std::vector<int32_t>& expected_int32_list =
+          int32_to_int32_list.at(sql_info_id);
+
+      // Assert the value (int32 list) has the correct size
+      ASSERT_EQ(expected_int32_list.size(), values.value_length(i));
+
+      // For each element on current ListScalar, assert it matches with the argument
+      for (size_t j = 0; j < expected_int32_list.size(); j++) {
+        ASSERT_OK_AND_ASSIGN(auto list_item_scalar,
+                             values.values()->GetScalar(values.value_offset(i) + j));
+        const auto& list_item = dynamic_cast<const Int32Scalar&>(*list_item_scalar).value;
+        ASSERT_EQ(expected_int32_list[j], list_item);
+      }
+    }
+  }
+
+  explicit SqlInfoDenseUnionValidator(const DenseUnionScalar& data) : data(data) {}
+
+  SqlInfoDenseUnionValidator(const SqlInfoDenseUnionValidator&) = delete;
+  SqlInfoDenseUnionValidator(SqlInfoDenseUnionValidator&&) = delete;
+  SqlInfoDenseUnionValidator& operator=(const SqlInfoDenseUnionValidator&) = delete;
+};
+
+std::unique_ptr<TestServer> server;
+std::unique_ptr<FlightSqlClient> sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server.reset(new TestServer("flight_sql_test_server"));
+    server->Start();
+    for (int i = 0; i < 100; i++) {
+      std::this_thread::sleep_for(std::chrono::milliseconds(10));
+      if (server->IsRunning()) {
+        break;
+      }
+    }
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+    server->Stop();
+    server.reset();
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array;
+  std::shared_ptr<Array> keyname_array;
+  std::shared_ptr<Array> value_array;
+  std::shared_ptr<Array> foreignId_array;
+  ArrayFromVector<Int64Type>({1, 2, 3}, &id_array);
+  ArrayFromVector<StringType, std::string>({"one", "zero", "negative one"},
+                                           &keyname_array);
+  ArrayFromVector<Int64Type>({1, 0, -1}, &value_array);
+  ArrayFromVector<Int64Type>({1, 1, 1}, &foreignId_array);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::vector<std::string> table_types;
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));

Review comment:
       This is not very readable, would recommend making the parameter names explicit, such as:
   ```c++
   sql_client->GetTables(/*options=*/{}, /*catalog=*/nullptr, ...

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any, const SqlInfoResultMap& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::ListActions(const ServerCallContext& context,
+                                        std::vector<ActionType>* actions) {
+  *actions = {FlightSqlServerBase::kCreatePreparedStatementActionType,
+              FlightSqlServerBase::kClosePreparedStatementActionType};
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::DoAction(const ServerCallContext& context,
+                                     const Action& action,
+                                     std::unique_ptr<ResultStream>* result_stream) {
+  if (action.type == FlightSqlServerBase::kCreatePreparedStatementActionType.type) {
+    google::protobuf::Any any_command;
+    if (!any_command.ParseFromArray(action.body->data(),
+                                    static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionCreatePreparedStatementRequest internal_command,
+                          ParseActionCreatePreparedStatementRequest(any_command));
+    ARROW_ASSIGN_OR_RAISE(auto result, CreatePreparedStatement(context, internal_command))
+
+    pb::sql::ActionCreatePreparedStatementResult action_result;
+    action_result.set_prepared_statement_handle(result.prepared_statement_handle);
+    if (result.dataset_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_dataset_schema,
+                            ipc::SerializeSchema(*result.dataset_schema))
+      action_result.set_dataset_schema(serialized_dataset_schema->ToString());
+    }
+    if (result.parameter_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_parameter_schema,
+                            ipc::SerializeSchema(*result.parameter_schema))
+      action_result.set_parameter_schema(serialized_parameter_schema->ToString());
+    }
+
+    google::protobuf::Any any;
+    any.PackFrom(action_result);
+
+    auto buf = Buffer::FromString(any.SerializeAsString());
+    *result_stream = std::unique_ptr<ResultStream>(new SimpleResultStream({Result{buf}}));
+
+    return Status::OK();
+  } else if (action.type == FlightSqlServerBase::kClosePreparedStatementActionType.type) {
+    google::protobuf::Any any;
+    if (!any.ParseFromArray(action.body->data(), static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionClosePreparedStatementRequest internal_command,
+                          ParseActionClosePreparedStatementRequest(any));
+
+    return ClosePreparedStatement(context, internal_command, result_stream);
+  }
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCatalogs(const ServerCallContext& context,
+                                                  const FlightDescriptor& descriptor,
+                                                  std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCatalogs(const ServerCallContext& context,
+                                          std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoStatement(const ServerCallContext& context,
+                                                   const StatementQuery& command,
+                                                   const FlightDescriptor& descriptor,
+                                                   std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetStatement(const ServerCallContext& context,
+                                           const StatementQueryTicket& command,
+                                           std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                                 const GetSqlInfo& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  assert(info != nullptr);
+
+  if (sql_info_id_to_result_.empty()) {
+    return Status::NotImplemented("GetFlightInfoSqlInfo not implemented");
+  }
+
+  std::vector<FlightEndpoint> endpoints{FlightEndpoint{{descriptor.cmd}, {}}};
+  ARROW_ASSIGN_OR_RAISE(auto result, FlightInfo::Make(*SqlSchema::GetSqlInfoSchema(),
+                                                      descriptor, endpoints, -1, -1))
+
+  *info = std::unique_ptr<FlightInfo>(new FlightInfo(result));
+
+  return Status::OK();
+}
+
+void FlightSqlServerBase::RegisterSqlInfo(int32_t id, const SqlInfoResult& result) {
+  sql_info_id_to_result_[id] = result;
+}
+
+Status FlightSqlServerBase::DoGetSqlInfo(const ServerCallContext& context,
+                                         const GetSqlInfo& command,
+                                         std::unique_ptr<FlightDataStream>* result) {
+  DCHECK(result);
+
+  MemoryPool* memory_pool = default_memory_pool();
+  UInt32Builder name_field_builder(memory_pool);
+  std::unique_ptr<ArrayBuilder> value_field_builder;
+  const auto& value_field_type = std::static_pointer_cast<DenseUnionType>(
+      SqlSchema::GetSqlInfoSchema()->fields()[1]->type());
+  ARROW_RETURN_NOT_OK(MakeBuilder(memory_pool, value_field_type, &value_field_builder));
+
+  internal::SqlInfoResultAppender sql_info_result_appender(
+      reinterpret_cast<DenseUnionBuilder&>(*value_field_builder));
+
+  // Populate both name_field_builder and value_field_builder for each element
+  // on command.info.
+  // value_field_builder is populated differently depending on the data type (as it is
+  // a DenseUnionBuilder). The population for each data type is implemented on
+  // internal::SqlInfoResultAppender.
+  for (const auto& info : command.info) {
+    if (!sql_info_id_to_result_.count(info)) {
+      return Status::KeyError(
+          "Attempt to fetch unregistered/unsupported SqlInfo option: " +
+          std::to_string(info));
+    }
+    ARROW_RETURN_NOT_OK(name_field_builder.Append(info));
+    ARROW_RETURN_NOT_OK(
+        arrow::util::visit(sql_info_result_appender, sql_info_id_to_result_.at(info)));

Review comment:
       We cannot simply raise an exception if `info` isn't found in `sql_info_to_result_`. Instead you should probably write something like:
   ```c++
       const auto it = sql_info_id_to_result_.find(info);
       if (it == sql_info_id_to_result_.end()) {
         return Status::KeyError("No information for SQL info number ", info);
       }
       ARROW_RETURN_NOT_OK(
           arrow::util::visit(sql_info_result_appender, it->second));
   ```

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_server.h
##########
@@ -0,0 +1,357 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "arrow/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"

Review comment:
       I'm 99% sure we don't want to make the protocol buffer generated definitions a public Arrow API, so this seems wrong to include them in an example.
   
   @lidavidm What do you think?

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -0,0 +1,783 @@
+// 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.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/api.h"
+#include "arrow/flight/sql/example/sqlite_server.h"
+#include "arrow/flight/test_util.h"
+#include "arrow/flight/types.h"
+#include "arrow/testing/gtest_util.h"
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+/// \brief Auxiliary variant visitor used to assert that GetSqlInfo's values are
+/// correctly placed on its DenseUnionArray
+class SqlInfoDenseUnionValidator {
+ private:
+  const DenseUnionScalar& data;
+
+ public:
+  /// \brief Asserts that the current DenseUnionScalar equals to given string value
+  void operator()(const std::string& string_value) const {
+    const auto& scalar = dynamic_cast<const StringScalar&>(*data.value);
+    ASSERT_EQ(string_value, scalar.ToString());
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given bool value
+  void operator()(const bool bool_value) const {
+    const auto& scalar = dynamic_cast<const BooleanScalar&>(*data.value);
+    ASSERT_EQ(bool_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int64_t value
+  void operator()(const int64_t bigint_value) const {
+    const auto& scalar = dynamic_cast<const Int64Scalar&>(*data.value);
+    ASSERT_EQ(bigint_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32_t value
+  void operator()(const int32_t int32_bitmask) const {
+    const auto& scalar = dynamic_cast<const Int32Scalar&>(*data.value);
+    ASSERT_EQ(int32_bitmask, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given string list
+  void operator()(const std::vector<std::string>& string_list) const {
+    const auto& array = dynamic_cast<const StringArray&>(
+        *(dynamic_cast<const ListScalar&>(*data.value).value));
+
+    ASSERT_EQ(string_list.size(), array.length());
+
+    for (size_t index = 0; index < string_list.size(); index++) {
+      ASSERT_EQ(string_list[index], array.GetString(index));
+    }
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32 to int32 list
+  /// map.
+  void operator()(const std::unordered_map<int32_t, std::vector<int32_t>>&
+                      int32_to_int32_list) const {
+    const auto& struct_array = dynamic_cast<const StructArray&>(
+        *dynamic_cast<const MapScalar&>(*data.value).value);
+    const auto& keys = dynamic_cast<const Int32Array&>(*struct_array.field(0));
+    const auto& values = dynamic_cast<const ListArray&>(*struct_array.field(1));
+
+    // Assert that the given map has the right size
+    ASSERT_EQ(int32_to_int32_list.size(), keys.length());
+
+    // For each element on given MapScalar, assert it matches the argument
+    for (int i = 0; i < keys.length(); i++) {
+      ASSERT_OK_AND_ASSIGN(const auto& key_scalar, keys.GetScalar(i));
+      int32_t sql_info_id = dynamic_cast<const Int32Scalar&>(*key_scalar).value;
+
+      // Assert the key (SqlInfo id) exists
+      ASSERT_TRUE(int32_to_int32_list.count(sql_info_id));
+
+      const std::vector<int32_t>& expected_int32_list =
+          int32_to_int32_list.at(sql_info_id);
+
+      // Assert the value (int32 list) has the correct size
+      ASSERT_EQ(expected_int32_list.size(), values.value_length(i));
+
+      // For each element on current ListScalar, assert it matches with the argument
+      for (size_t j = 0; j < expected_int32_list.size(); j++) {
+        ASSERT_OK_AND_ASSIGN(auto list_item_scalar,
+                             values.values()->GetScalar(values.value_offset(i) + j));
+        const auto& list_item = dynamic_cast<const Int32Scalar&>(*list_item_scalar).value;
+        ASSERT_EQ(expected_int32_list[j], list_item);
+      }
+    }
+  }
+
+  explicit SqlInfoDenseUnionValidator(const DenseUnionScalar& data) : data(data) {}
+
+  SqlInfoDenseUnionValidator(const SqlInfoDenseUnionValidator&) = delete;
+  SqlInfoDenseUnionValidator(SqlInfoDenseUnionValidator&&) = delete;
+  SqlInfoDenseUnionValidator& operator=(const SqlInfoDenseUnionValidator&) = delete;
+};
+
+std::unique_ptr<TestServer> server;
+std::unique_ptr<FlightSqlClient> sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server.reset(new TestServer("flight_sql_test_server"));
+    server->Start();
+    for (int i = 0; i < 100; i++) {
+      std::this_thread::sleep_for(std::chrono::milliseconds(10));
+      if (server->IsRunning()) {
+        break;
+      }
+    }
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+    server->Stop();
+    server.reset();
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array;
+  std::shared_ptr<Array> keyname_array;
+  std::shared_ptr<Array> value_array;
+  std::shared_ptr<Array> foreignId_array;
+  ArrayFromVector<Int64Type>({1, 2, 3}, &id_array);
+  ArrayFromVector<StringType, std::string>({"one", "zero", "negative one"},
+                                           &keyname_array);
+  ArrayFromVector<Int64Type>({1, 0, -1}, &value_array);
+  ArrayFromVector<Int64Type>({1, 1, 1}, &foreignId_array);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::vector<std::string> table_types;
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {"foreignTable", "intTable", "sqlite_sequence"}, &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);

Review comment:
       ```c++
   auto table_type = ArrayFromJSON(utf8(), R"(["table", "table", "table"])");
   ```

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_server.h
##########
@@ -0,0 +1,357 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "arrow/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+#include "arrow/flight/sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+namespace flight_sql_pb = arrow::flight::protocol::sql;
+
+/// \brief Gets the mapping from SQL info ids to SqlInfoResult instances.
+/// \return the cache.
+inline SqlInfoResultMap GetSqlInfoResultMap() {
+  return {
+      {flight_sql_pb::SqlInfo::FLIGHT_SQL_SERVER_NAME,
+       SqlInfoResult(std::string("db_name"))},
+      {flight_sql_pb::SqlInfo::FLIGHT_SQL_SERVER_VERSION,
+       SqlInfoResult(std::string("sqlite 3"))},
+      {flight_sql_pb::SqlInfo::FLIGHT_SQL_SERVER_ARROW_VERSION,
+       SqlInfoResult(std::string("7.0.0-SNAPSHOT" /* Only an example */))},
+      {flight_sql_pb::SqlInfo::FLIGHT_SQL_SERVER_READ_ONLY, SqlInfoResult(false)},
+      {flight_sql_pb::SqlInfo::SQL_DDL_CATALOG,
+       SqlInfoResult(false /* SQLite 3 does not support catalogs */)},
+      {flight_sql_pb::SqlInfo::SQL_DDL_SCHEMA,
+       SqlInfoResult(false /* SQLite 3 does not support schemas */)},
+      {flight_sql_pb::SqlInfo::SQL_DDL_TABLE, SqlInfoResult(true)},
+      {flight_sql_pb::SqlInfo::SQL_IDENTIFIER_CASE,
+       SqlInfoResult(int64_t(flight_sql_pb::SqlSupportedCaseSensitivity::
+                                 SQL_CASE_SENSITIVITY_CASE_INSENSITIVE))},
+      {flight_sql_pb::SqlInfo::SQL_IDENTIFIER_QUOTE_CHAR,
+       SqlInfoResult(std::string("\""))},
+      {flight_sql_pb::SqlInfo::SQL_QUOTED_IDENTIFIER_CASE,
+       SqlInfoResult(int64_t(flight_sql_pb::SqlSupportedCaseSensitivity::
+                                 SQL_CASE_SENSITIVITY_CASE_INSENSITIVE))},
+      {flight_sql_pb::SqlInfo::SQL_ALL_TABLES_ARE_SELECTABLE, SqlInfoResult(true)},
+      {flight_sql_pb::SqlInfo::SQL_NULL_ORDERING,
+       SqlInfoResult(int64_t(flight_sql_pb::SqlNullOrdering::SQL_NULLS_SORTED_AT_START))},
+      {flight_sql_pb::SqlInfo::SQL_KEYWORDS,
+       SqlInfoResult(std::vector<std::string>({"ABORT",
+                                               "ACTION",
+                                               "ADD",
+                                               "AFTER",
+                                               "ALL",
+                                               "ALTER",
+                                               "ALWAYS",
+                                               "ANALYZE",
+                                               "AND",
+                                               "AS",
+                                               "ASC",
+                                               "ATTACH",
+                                               "AUTOINCREMENT",
+                                               "BEFORE",
+                                               "BEGIN",
+                                               "BETWEEN",
+                                               "BY",
+                                               "CASCADE",
+                                               "CASE",
+                                               "CAST",
+                                               "CHECK",
+                                               "COLLATE",
+                                               "COLUMN",
+                                               "COMMIT",
+                                               "CONFLICT",
+                                               "CONSTRAINT",
+                                               "CREATE",
+                                               "CROSS",
+                                               "CURRENT",
+                                               "CURRENT_DATE",
+                                               "CURRENT_TIME",
+                                               "CURRENT_TIMESTAMP",
+                                               "DATABASE",
+                                               "DEFAULT",
+                                               "DEFERRABLE",
+                                               "DEFERRED",
+                                               "DELETE",
+                                               "DESC",
+                                               "DETACH",
+                                               "DISTINCT",
+                                               "DO",
+                                               "DROP",
+                                               "EACH",
+                                               "ELSE",
+                                               "END",
+                                               "ESCAPE",
+                                               "EXCEPT",
+                                               "EXCLUDE",
+                                               "EXCLUSIVE",
+                                               "EXISTS",
+                                               "EXPLAIN",
+                                               "FAIL",
+                                               "FILTER",
+                                               "FIRST",
+                                               "FOLLOWING",
+                                               "FOR",
+                                               "FOREIGN",
+                                               "FROM",
+                                               "FULL",
+                                               "GENERATED",
+                                               "GLOB",
+                                               "GROUP",
+                                               "GROUPS",
+                                               "HAVING",
+                                               "IF",
+                                               "IGNORE",
+                                               "IMMEDIATE",
+                                               "IN",
+                                               "INDEX",
+                                               "INDEXED",
+                                               "INITIALLY",
+                                               "INNER",
+                                               "INSERT",
+                                               "INSTEAD",
+                                               "INTERSECT",
+                                               "INTO",
+                                               "IS",
+                                               "ISNULL",
+                                               "JOIN",
+                                               "KEY",
+                                               "LAST",
+                                               "LEFT",
+                                               "LIKE",
+                                               "LIMIT",
+                                               "MATCH",
+                                               "MATERIALIZED",
+                                               "NATURAL",
+                                               "NO",
+                                               "NOT",
+                                               "NOTHING",
+                                               "NOTNULL",
+                                               "NULL",
+                                               "NULLS",
+                                               "OF",
+                                               "OFFSET",
+                                               "ON",
+                                               "OR",
+                                               "ORDER",
+                                               "OTHERS",
+                                               "OUTER",
+                                               "OVER",
+                                               "PARTITION",
+                                               "PLAN",
+                                               "PRAGMA",
+                                               "PRECEDING",
+                                               "PRIMARY",
+                                               "QUERY",
+                                               "RAISE",
+                                               "RANGE",
+                                               "RECURSIVE",
+                                               "REFERENCES",
+                                               "REGEXP",
+                                               "REINDEX",
+                                               "RELEASE",
+                                               "RENAME",
+                                               "REPLACE",
+                                               "RESTRICT",
+                                               "RETURNING",
+                                               "RIGHT",
+                                               "ROLLBACK",
+                                               "ROW",
+                                               "ROWS",
+                                               "SAVEPOINT",
+                                               "SELECT",
+                                               "SET",
+                                               "TABLE",
+                                               "TEMP",
+                                               "TEMPORARY",
+                                               "THEN",
+                                               "TIES",
+                                               "TO",
+                                               "TRANSACTION",
+                                               "TRIGGER",
+                                               "UNBOUNDED",
+                                               "UNION",
+                                               "UNIQUE",
+                                               "UPDATE",
+                                               "USING",
+                                               "VACUUM",
+                                               "VALUES",
+                                               "VIEW",
+                                               "VIRTUAL",
+                                               "WHEN",
+                                               "WHERE",
+                                               "WINDOW",
+                                               "WITH",
+                                               "WITHOUT"}))},
+      {flight_sql_pb::SqlInfo::SQL_NUMERIC_FUNCTIONS,
+       SqlInfoResult(std::vector<std::string>(
+           {"acos",    "acosh", "asin", "asinh",   "atan", "atan2", "atanh", "ceil",
+            "ceiling", "cos",   "cosh", "degrees", "exp",  "floor", "ln",    "log",
+            "log",     "log10", "log2", "mod",     "pi",   "pow",   "power", "radians",
+            "sin",     "sinh",  "sqrt", "tan",     "tanh", "trunc"}))},
+      {flight_sql_pb::SqlInfo::SQL_STRING_FUNCTIONS,
+       SqlInfoResult(
+           std::vector<std::string>({"SUBSTR", "TRIM", "LTRIM", "RTRIM", "LENGTH",
+                                     "REPLACE", "UPPER", "LOWER", "INSTR"}))},
+      {flight_sql_pb::SqlInfo::SQL_SUPPORTS_CONVERT,
+       SqlInfoResult(std::unordered_map<int32_t, std::vector<int32_t>>(
+           {{flight_sql_pb::SqlSupportsConvert::SQL_CONVERT_BIGINT,
+             std::vector<int32_t>(
+                 {flight_sql_pb::SqlSupportsConvert::SQL_CONVERT_INTEGER})}}))}};
+}
+
+/// \brief Convert a column type to a ArrowType.
+/// \param sqlite_type the sqlite type.
+/// \return            The equivalent ArrowType.
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type);
+
+/// \brief  Get the DataType used when parameter type is not known.
+/// \return DataType used when parameter type is not known.
+inline std::shared_ptr<DataType> GetUnknownColumnDataType() {
+  return dense_union({
+      field("string", utf8()),
+      field("bytes", binary()),
+      field("bigint", int64()),
+      field("double", float64()),
+  });
+}
+
+/// \brief Example implementation of FlightSqlServerBase backed by an in-memory SQLite3
+///        database.
+class SQLiteFlightSqlServer : public FlightSqlServerBase {
+ public:
+  ~SQLiteFlightSqlServer() override;
+
+  static arrow::Result<std::shared_ptr<SQLiteFlightSqlServer>> Create();
+
+  /// \brief Auxiliary method used to execute an arbitrary SQL statement on the underlying
+  ///        SQLite database.
+  Status ExecuteSql(const std::string& sql);
+
+  Status GetFlightInfoStatement(const ServerCallContext& context,
+                                const StatementQuery& command,
+                                const FlightDescriptor& descriptor,
+                                std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGetStatement(const ServerCallContext& context,
+                        const StatementQueryTicket& command,
+                        std::unique_ptr<FlightDataStream>* result) override;
+  Status GetFlightInfoCatalogs(const ServerCallContext& context,
+                               const FlightDescriptor& descriptor,
+                               std::unique_ptr<FlightInfo>* info) override;
+  Status DoGetCatalogs(const ServerCallContext& context,
+                       std::unique_ptr<FlightDataStream>* result) override;
+  Status GetFlightInfoSchemas(const ServerCallContext& context, const GetSchemas& command,
+                              const FlightDescriptor& descriptor,
+                              std::unique_ptr<FlightInfo>* info) override;
+  Status DoGetSchemas(const ServerCallContext& context, const GetSchemas& command,
+                      std::unique_ptr<FlightDataStream>* result) override;
+  arrow::Result<int64_t> DoPutCommandStatementUpdate(
+      const ServerCallContext& context, const StatementUpdate& update,
+      std::unique_ptr<FlightMessageReader>& reader) override;
+  arrow::Result<ActionCreatePreparedStatementResult> CreatePreparedStatement(
+      const ServerCallContext& context,
+      const ActionCreatePreparedStatementRequest& request) override;
+  Status ClosePreparedStatement(const ServerCallContext& context,
+                                const ActionClosePreparedStatementRequest& request,
+                                std::unique_ptr<ResultStream>* result) override;
+  Status GetFlightInfoPreparedStatement(const ServerCallContext& context,
+                                        const PreparedStatementQuery& command,
+                                        const FlightDescriptor& descriptor,
+                                        std::unique_ptr<FlightInfo>* info) override;
+  Status DoGetPreparedStatement(const ServerCallContext& context,
+                                const PreparedStatementQuery& command,
+                                std::unique_ptr<FlightDataStream>* result) override;
+  Status DoPutPreparedStatementQuery(const ServerCallContext& context,
+                                     const PreparedStatementQuery& command,
+                                     FlightMessageReader* reader,
+                                     FlightMetadataWriter* writer) override;
+  arrow::Result<int64_t> DoPutPreparedStatementUpdate(
+      const ServerCallContext& context, const PreparedStatementUpdate& command,
+      FlightMessageReader* reader) override;
+
+  Status GetFlightInfoTables(const ServerCallContext& context, const GetTables& command,
+                             const FlightDescriptor& descriptor,
+                             std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGetTables(const ServerCallContext& context, const GetTables& command,
+                     std::unique_ptr<FlightDataStream>* result) override;
+  Status GetFlightInfoTableTypes(const ServerCallContext& context,
+                                 const FlightDescriptor& descriptor,
+                                 std::unique_ptr<FlightInfo>* info) override;
+  Status DoGetTableTypes(const ServerCallContext& context,
+                         std::unique_ptr<FlightDataStream>* result) override;
+  Status GetFlightInfoImportedKeys(const ServerCallContext& context,
+                                   const GetImportedKeys& command,
+                                   const FlightDescriptor& descriptor,
+                                   std::unique_ptr<FlightInfo>* info) override;
+  Status DoGetImportedKeys(const ServerCallContext& context,
+                           const GetImportedKeys& command,
+                           std::unique_ptr<FlightDataStream>* result) override;
+  Status GetFlightInfoExportedKeys(const ServerCallContext& context,
+                                   const GetExportedKeys& command,
+                                   const FlightDescriptor& descriptor,
+                                   std::unique_ptr<FlightInfo>* info) override;
+  Status DoGetExportedKeys(const ServerCallContext& context,
+                           const GetExportedKeys& command,
+                           std::unique_ptr<FlightDataStream>* result) override;
+  Status GetFlightInfoCrossReference(const ServerCallContext& context,
+                                     const GetCrossReference& command,
+                                     const FlightDescriptor& descriptor,
+                                     std::unique_ptr<FlightInfo>* info) override;
+  Status DoGetCrossReference(const ServerCallContext& context,
+                             const GetCrossReference& command,
+                             std::unique_ptr<FlightDataStream>* result) override;
+
+  Status GetFlightInfoPrimaryKeys(const ServerCallContext& context,
+                                  const GetPrimaryKeys& command,
+                                  const FlightDescriptor& descriptor,
+                                  std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGetPrimaryKeys(const ServerCallContext& context, const GetPrimaryKeys& command,
+                          std::unique_ptr<FlightDataStream>* result) override;
+
+ private:
+  sqlite3* db_;
+  boost::uuids::random_generator uuid_generator_;
+  std::map<boost::uuids::uuid, std::shared_ptr<SqliteStatement>> prepared_statements_;

Review comment:
       Two things:
   1) why use UUIDs? this seems unnecessary, a regular random string should do, and it would avoid an additional Boost dependency
   2) better to hide implementation details in the `.cc`, for example using the pimpl idiom:
   ```c++
   struct Impl;
   std::shared_ptr<Impl> impl_;
   ```

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_server.cc
##########
@@ -0,0 +1,684 @@
+// 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/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid_io.hpp>
+
+#include "arrow/api.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+#include "arrow/flight/sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/sql/example/sqlite_tables_schema_batch_reader.h"
+#include "arrow/flight/sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+namespace {
+
+/// \brief Gets a SqliteStatement by given handle
+arrow::Result<std::shared_ptr<SqliteStatement>> GetStatementByHandle(
+    const std::map<boost::uuids::uuid, std::shared_ptr<SqliteStatement>>&
+        prepared_statements,
+    const std::string& handle) {
+  const auto& uuid = boost::lexical_cast<boost::uuids::uuid>(handle);
+
+  auto search = prepared_statements.find(uuid);
+  if (search == prepared_statements.end()) {
+    return Status::Invalid("Prepared statement not found");
+  }
+
+  return search->second;
+}
+
+std::string PrepareQueryForGetTables(const GetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.catalog.has_value()) {
+    table_query << " and catalog_name='" << command.catalog.value() << "'";
+  }
+
+  if (command.schema_filter_pattern.has_value()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern.value()
+                << "'";
+  }
+
+  if (command.table_name_filter_pattern.has_value()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern.value()
+                << "'";
+  }
+
+  if (!command.table_types.empty()) {
+    table_query << " and table_type IN (";
+    size_t size = command.table_types.size();
+    for (size_t i = 0; i < size; i++) {
+      table_query << "'" << command.table_types[i] << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt, FlightMessageReader* reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = static_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = static_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = static_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer = static_cast<StringScalar&>(*holder).value;
+            sqlite3_bind_text(stmt, c + 1, reinterpret_cast<const char*>(buffer->data()),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer = static_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+}  // namespace
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    throw std::invalid_argument("Invalid SQLite type: " + std::string(sqlite_type));
+  }
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer(sqlite3* db) : db_(db), uuid_generator_({}) {
+  assert(db_);
+}
+
+arrow::Result<std::shared_ptr<SQLiteFlightSqlServer>> SQLiteFlightSqlServer::Create() {
+  sqlite3* db = nullptr;
+
+  if (sqlite3_open(":memory:", &db)) {
+    std::string err_msg = "Can't open database: ";
+    if (db != nullptr) {
+      err_msg += sqlite3_errmsg(db);
+      sqlite3_close(db);
+    } else {
+      err_msg += "Unable to start SQLite. Insufficient memory";
+    }
+
+    return Status::Invalid(err_msg);
+  }
+
+  std::shared_ptr<SQLiteFlightSqlServer> result(new SQLiteFlightSqlServer(db));
+  for (const auto& id_to_result : GetSqlInfoResultMap()) {
+    result->RegisterSqlInfo(id_to_result.first, id_to_result.second);
+  }
+
+  ARROW_RETURN_NOT_OK(result->ExecuteSql(R"(
+    CREATE TABLE foreignTable (
+    id INTEGER PRIMARY KEY AUTOINCREMENT,
+    foreignName varchar(100),
+    value int);
+
+    CREATE TABLE intTable (
+    id INTEGER PRIMARY KEY AUTOINCREMENT,
+    keyName varchar(100),
+    value int,
+    foreignId int references foreignTable(id));
+
+    INSERT INTO foreignTable (foreignName, value) VALUES ('keyOne', 1);
+    INSERT INTO foreignTable (foreignName, value) VALUES ('keyTwo', 0);
+    INSERT INTO foreignTable (foreignName, value) VALUES ('keyThree', -1);
+    INSERT INTO intTable (keyName, value, foreignId) VALUES ('one', 1, 1);
+    INSERT INTO intTable (keyName, value, foreignId) VALUES ('zero', 0, 1);
+    INSERT INTO intTable (keyName, value, foreignId) VALUES ('negative one', -1, 1);

Review comment:
       I would expect some NULLs in the example tables.

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any, const SqlInfoResultMap& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =

Review comment:
       Using a const-ref is a bit weird here since `Buffer::FromString` is creating a new instance.
   

##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any, const SqlInfoResultMap& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::ListActions(const ServerCallContext& context,
+                                        std::vector<ActionType>* actions) {
+  *actions = {FlightSqlServerBase::kCreatePreparedStatementActionType,
+              FlightSqlServerBase::kClosePreparedStatementActionType};
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::DoAction(const ServerCallContext& context,
+                                     const Action& action,
+                                     std::unique_ptr<ResultStream>* result_stream) {
+  if (action.type == FlightSqlServerBase::kCreatePreparedStatementActionType.type) {
+    google::protobuf::Any any_command;
+    if (!any_command.ParseFromArray(action.body->data(),
+                                    static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionCreatePreparedStatementRequest internal_command,
+                          ParseActionCreatePreparedStatementRequest(any_command));
+    ARROW_ASSIGN_OR_RAISE(auto result, CreatePreparedStatement(context, internal_command))
+
+    pb::sql::ActionCreatePreparedStatementResult action_result;
+    action_result.set_prepared_statement_handle(result.prepared_statement_handle);
+    if (result.dataset_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_dataset_schema,
+                            ipc::SerializeSchema(*result.dataset_schema))
+      action_result.set_dataset_schema(serialized_dataset_schema->ToString());
+    }
+    if (result.parameter_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_parameter_schema,
+                            ipc::SerializeSchema(*result.parameter_schema))
+      action_result.set_parameter_schema(serialized_parameter_schema->ToString());
+    }
+
+    google::protobuf::Any any;
+    any.PackFrom(action_result);
+
+    auto buf = Buffer::FromString(any.SerializeAsString());
+    *result_stream = std::unique_ptr<ResultStream>(new SimpleResultStream({Result{buf}}));
+
+    return Status::OK();
+  } else if (action.type == FlightSqlServerBase::kClosePreparedStatementActionType.type) {
+    google::protobuf::Any any;
+    if (!any.ParseFromArray(action.body->data(), static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionClosePreparedStatementRequest internal_command,
+                          ParseActionClosePreparedStatementRequest(any));
+
+    return ClosePreparedStatement(context, internal_command, result_stream);
+  }
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCatalogs(const ServerCallContext& context,
+                                                  const FlightDescriptor& descriptor,
+                                                  std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCatalogs(const ServerCallContext& context,
+                                          std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoStatement(const ServerCallContext& context,
+                                                   const StatementQuery& command,
+                                                   const FlightDescriptor& descriptor,
+                                                   std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetStatement(const ServerCallContext& context,
+                                           const StatementQueryTicket& command,
+                                           std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                                 const GetSqlInfo& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  assert(info != nullptr);
+
+  if (sql_info_id_to_result_.empty()) {
+    return Status::NotImplemented("GetFlightInfoSqlInfo not implemented");
+  }
+
+  std::vector<FlightEndpoint> endpoints{FlightEndpoint{{descriptor.cmd}, {}}};
+  ARROW_ASSIGN_OR_RAISE(auto result, FlightInfo::Make(*SqlSchema::GetSqlInfoSchema(),
+                                                      descriptor, endpoints, -1, -1))
+
+  *info = std::unique_ptr<FlightInfo>(new FlightInfo(result));
+
+  return Status::OK();
+}
+
+void FlightSqlServerBase::RegisterSqlInfo(int32_t id, const SqlInfoResult& result) {
+  sql_info_id_to_result_[id] = result;
+}
+
+Status FlightSqlServerBase::DoGetSqlInfo(const ServerCallContext& context,
+                                         const GetSqlInfo& command,
+                                         std::unique_ptr<FlightDataStream>* result) {
+  DCHECK(result);
+
+  MemoryPool* memory_pool = default_memory_pool();
+  UInt32Builder name_field_builder(memory_pool);
+  std::unique_ptr<ArrayBuilder> value_field_builder;
+  const auto& value_field_type = std::static_pointer_cast<DenseUnionType>(
+      SqlSchema::GetSqlInfoSchema()->fields()[1]->type());
+  ARROW_RETURN_NOT_OK(MakeBuilder(memory_pool, value_field_type, &value_field_builder));
+
+  internal::SqlInfoResultAppender sql_info_result_appender(
+      reinterpret_cast<DenseUnionBuilder&>(*value_field_builder));

Review comment:
       Use `checked_cast` here.

##########
File path: cpp/src/arrow/flight/sql/example/sqlite_server.cc
##########
@@ -0,0 +1,684 @@
+// 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/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>

Review comment:
       Why are these Boost headers all required?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-981920045


   It seems the C++ server tests may be flaky? From the [AMD64 Conda C++ logs](https://github.com/apache/arrow/runs/4343704927?check_suite_focus=true):
   
   ```
   [----------] 20 tests from TestFlightSqlServer
   [ RUN      ] TestFlightSqlServer.TestCommandStatementQuery
   /arrow/cpp/src/arrow/flight/sql/server_test.cc:163: Failure
   Failed
   '_error_or_value25.status()' failed with IOError: gRPC returned unavailable error, with message: failed to connect to all addresses. Detail: Unavailable
   [  FAILED  ] TestFlightSqlServer.TestCommandStatementQuery (0 ms)
   [ RUN      ] TestFlightSqlServer.TestCommandGetTables
   /arrow/cpp/src/arrow/flight/sql/server_test.cc:195: Failure
   Failed
   '_error_or_value27.status()' failed with IOError: gRPC returned unavailable error, with message: failed to connect to all addresses. Detail: Unavailable
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-977865623


   I am reviewing the C++ parts, but briefly a high-level concern: the spec and/or the implementation seems to overload the term "schema" for a different thing than the usual concept of an Arrow schema (which exists in C++ but also in Java and in the Arrow format spec itself). Would it be possible to find another term?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756029938



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null

Review comment:
       Ok, can it be explained briefly as a comment somewhere?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r749686620



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -87,7 +83,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
 
   add_executable(flight_sql_test_server
                  server.cc
-                 sql_info_util.cc
+                 sql_info_internal.cc

Review comment:
       Ops... didn't need link it, fixed




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-954746311


   It looks like we'll have to merge the Java PR first when time comes since the current Java Protobuf setup can't handle the `optional` fields.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r752433801



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name, then schema_name.
+ */
+message CommandGetSchemas {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, the pattern will not be used to narrow the search.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+}
+
+/*
+ * Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  table_type: utf8 not null,
+ *  [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema,
+ *                                           it is serialized as an IPC message.)
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, then table_type, followed by table_schema if requested.
+ */
+message CommandGetTables {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, all schemas matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+
+  /*
+   * Specifies a filter pattern for tables to search for.
+   * When no table_name_filter_pattern is provided, all tables matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string table_name_filter_pattern = 3;
+
+  // Specifies a filter of table types which must match.
+  repeated string table_types = 4;
+
+  // Specifies if the schema should be returned for found tables.
+  bool include_schema = 5;
+}
+
+/*
+ * Represents a request to retrieve the list of table types on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  table_type: utf8 not null
+ * >
+ * The returned data should be ordered by table_type.
+ */
+message CommandGetTableTypes {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the primary keys of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  column_name: utf8 not null,
+ *  key_name: utf8,
+ *  key_sequence: int not null
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, key_name, then key_sequence.
+ */
+message CommandGetPrimaryKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the table to get the primary keys for.
+  string table = 3;
+}
+
+enum UpdateDeleteRules {
+  CASCADE = 0;
+  RESTRICT = 1;
+  SET_NULL = 2;
+  NO_ACTION = 3;
+  SET_DEFAULT = 4;
+}
+
+/*
+ * Represents a request to retrieve a description of the foreign key columns that reference the given table's
+ * primary key columns (the foreign keys exported by a table) of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by fk_catalog_name, fk_schema_name, fk_table_name, fk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions declared on UpdateDeleteRules enum.
+ */
+message CommandGetExportedKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the foreign key table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the foreign key table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the foreign key table to get the foreign keys for.
+  string table = 3;
+}
+
+/*
+ * Represents a request to retrieve the foreign keys of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by pk_catalog_name, pk_schema_name, pk_table_name, pk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions:
+ *    - 0 = CASCADE
+ *    - 1 = RESTRICT
+ *    - 2 = SET NULL
+ *    - 3 = NO ACTION
+ *    - 4 = SET DEFAULT
+ */
+message CommandGetImportedKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the primary key table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the primary key table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the primary key table to get the foreign keys for.
+  string table = 3;
+}
+
+/*
+ * Represents a request to retrieve a description of the foreign key columns in the given foreign key table that
+ * reference the primary key or the columns representing a unique constraint of the parent table (could be the same
+ * or a different table) on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by pk_catalog_name, pk_schema_name, pk_table_name, pk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions:
+ *    - 0 = CASCADE
+ *    - 1 = RESTRICT
+ *    - 2 = SET NULL
+ *    - 3 = NO ACTION
+ *    - 4 = SET DEFAULT
+ */
+message CommandGetCrossReference {
+  option (experimental) = true;
+
+  /**
+   * The catalog name where the parent table is.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string pk_catalog = 1;
+
+  /**
+   * The Schema name where the parent table is.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string pk_schema = 2;
+
+  /**
+   * The parent table name. It cannot be null.
+   */
+  string pk_table = 3;
+
+  /**
+   * The catalog name where the foreign table is.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string fk_catalog = 4;
+
+  /**
+   * The schema name where the foreign table is.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string fk_schema = 5;
+
+  /**
+   * The foreign table name. It cannot be null.
+   */
+  string fk_table = 6;
+}
+
+// SQL Execution Action Messages
+
+/*
+ * Request message for the "CreatePreparedStatement" action on a Flight SQL enabled backend.
+ */
+message ActionCreatePreparedStatementRequest {
+  option (experimental) = true;
+
+  // The valid SQL string to create a prepared statement for.
+  string query = 1;
+}
+
+/*
+ * Wrap the result of a "GetPreparedStatement" action.
+ *
+ * The resultant PreparedStatement can be closed either:
+ * - Manually, through the "ClosePreparedStatement" action;
+ * - Automatically, by a server timeout.
+ */
+message ActionCreatePreparedStatementResult {
+  option (experimental) = true;
+
+  // Opaque handle for the prepared statement on the server.
+  bytes prepared_statement_handle = 1;
+
+  // If a result set generating query was provided, dataset_schema contains the 
+  // schema of the dataset as described in Schema.fbs::Schema, it is serialized as an IPC message.
+  bytes dataset_schema = 2;
+
+  // If the query provided contained parameters, parameter_schema contains the 
+  // schema of the expected parameters as described in Schema.fbs::Schema, it is serialized as an IPC message.
+  bytes parameter_schema = 3;
+}
+
+/*
+ * Request message for the "ClosePreparedStatement" action on a Flight SQL enabled backend.
+ * Closes server resources associated with the prepared statement handle.
+ */
+message ActionClosePreparedStatementRequest {
+  option (experimental) = true;
+
+  // Opaque handle for the prepared statement on the server.
+  bytes prepared_statement_handle = 1;
+}
+
+
+// SQL Execution Messages.
+
+/*
+ * Represents a SQL query. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the query.
+ */
+message CommandStatementQuery {
+  option (experimental) = true;
+
+  // The SQL syntax.
+  string query = 1;
+}
+
+/**
+ * Represents a ticket resulting from GetFlightInfo with a CommandStatementQuery.
+ * This should be treated as an opaque value, that is, clients should not attempt to parse this.
+ */
+message TicketStatementQuery {
+  option (experimental) = true;
+
+  // Unique identifier for the instance of the statement to execute.
+  bytes statement_handle = 1;

Review comment:
       It's valid for only 1 usage




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-952386261


   Sure! Here it is: https://gist.github.com/rafael-telles/14e39ae4d8856e78b5517bf69960843d
   
   Thank you so much for helping us with this issue :)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735858588



##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,172 @@
+// 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/flight-sql/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);                   \
+    if (string == nullptr) {                                                           \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes));          \
+    break;                                                                             \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes));     \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                    \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);                         \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define FLOAT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    double value = sqlite3_column_double(STMT, COLUMN);                               \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define MAX_BATCH_SIZE 1024
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<Schema> SqliteStatementBatchReader::schema() const { return schema_; }
+
+SqliteStatementBatchReader::SqliteStatementBatchReader(
+    std::shared_ptr<SqliteStatement> statement, std::shared_ptr<Schema> schema)
+    : statement_(std::move(statement)), schema_(std::move(schema)) {

Review comment:
       So one reason for the failures is this doesn't initialize all the fields.

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,172 @@
+// 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/flight-sql/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);                   \
+    if (string == nullptr) {                                                           \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes));          \
+    break;                                                                             \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes));     \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                    \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);                         \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define FLOAT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    double value = sqlite3_column_double(STMT, COLUMN);                               \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define MAX_BATCH_SIZE 1024
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<Schema> SqliteStatementBatchReader::schema() const { return schema_; }
+
+SqliteStatementBatchReader::SqliteStatementBatchReader(
+    std::shared_ptr<SqliteStatement> statement, std::shared_ptr<Schema> schema)
+    : statement_(std::move(statement)), schema_(std::move(schema)) {
+  rc = SQLITE_OK;

Review comment:
       ```suggestion
       : statement_(std::move(statement)), schema_(std::move(schema)), rc(SQLITE_OK), already_executed(false) {
   ```

##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,172 @@
+// 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/flight-sql/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);                   \
+    if (string == nullptr) {                                                           \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes));          \
+    break;                                                                             \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes));     \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                    \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);                         \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define FLOAT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    double value = sqlite3_column_double(STMT, COLUMN);                               \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define MAX_BATCH_SIZE 1024
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<Schema> SqliteStatementBatchReader::schema() const { return schema_; }
+
+SqliteStatementBatchReader::SqliteStatementBatchReader(
+    std::shared_ptr<SqliteStatement> statement, std::shared_ptr<Schema> schema)
+    : statement_(std::move(statement)), schema_(std::move(schema)) {
+  rc = SQLITE_OK;

Review comment:
       Also the naming scheme here is inconsistent (use rc_, already_executed_)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742111758



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Hey @lidavidm ! Can you please clarify?

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       We are defining FlightClientImpl on `client_test.cc` and `client_internal.cc`, made sure that we are not building or linking them at any time on CMakeLists.txt

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Oops, didn't see your last comment!
   I thought that as it was statically linking libarrow_flight_sql(containing client_internal.cc) when building client_test.cc it could be a problem.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Hey @lidavidm ! Can you please clarify?

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       We are defining FlightClientImpl on `client_test.cc` and `client_internal.cc`, made sure that we are not building or linking them at any time on CMakeLists.txt

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Oops, didn't see your last comment!
   I thought that as it was statically linking libarrow_flight_sql(containing client_internal.cc) when building client_test.cc it could be a problem.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742331746



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Er, sorry for the churn @rafael-telles but I think the latest commit is strictly worse. I think the situation is OK as-is so long as it's clearly documented (and I can't claim to be a linker expert or C++ standard expert so maybe this is all OK and I don't understand the reason why). I'm mostly just concerned that it's unclear what the intent is.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r743911807



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       This appears to fix it for me, by avoiding linking Protobuf in multiple times:
   
   @rafael-telles does this work for you?
   
   ```diff
   diff --git a/cpp/src/arrow/flight/CMakeLists.txt b/cpp/src/arrow/flight/CMakeLists.txt
   index 309e5a968..66776424e 100644
   --- a/cpp/src/arrow/flight/CMakeLists.txt
   +++ b/cpp/src/arrow/flight/CMakeLists.txt
   @@ -27,11 +27,14 @@ endif()
    
    if(ARROW_TEST_LINKAGE STREQUAL "static")
      set(ARROW_FLIGHT_TEST_LINK_LIBS
   -      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
   +      arrow_flight_static
   +      arrow_flight_testing_static
   +      ${ARROW_FLIGHT_STATIC_LINK_LIBS}
   +      gRPC::grpc++
          ${ARROW_TEST_LINK_LIBS})
    else()
      set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
   -                                  ${ARROW_TEST_LINK_LIBS})
   +                                  gRPC::grpc++ ${ARROW_TEST_LINK_LIBS})
    endif()
    
    # TODO(wesm): Protobuf shared vs static linking
   @@ -165,6 +168,7 @@ add_arrow_lib(arrow_flight
                  ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
                  SHARED_LINK_LIBS
                  arrow_shared
   +              SHARED_PRIVATE_LINK_LIBS
                  ${ARROW_FLIGHT_LINK_LIBS}
                  STATIC_LINK_LIBS
                  arrow_static
   diff --git a/cpp/src/arrow/flight/flight_sql/CMakeLists.txt b/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   index fd453ccc5..8fd852909 100644
   --- a/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   +++ b/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   @@ -36,7 +36,8 @@ set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENER
    
    add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
    
   -set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc client_internal.cc)
   +set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc client_internal.cc
   +                          "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
    
    add_arrow_lib(arrow_flight_sql
                  CMAKE_PACKAGE_NAME
   @@ -51,10 +52,13 @@ add_arrow_lib(arrow_flight_sql
                  "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
                  DEPENDENCIES
                  flight_sql_protobuf_gen
   +              toolchain
                  SHARED_LINK_FLAGS
                  ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
                  SHARED_LINK_LIBS
                  arrow_flight_shared
   +              SHARED_PRIVATE_LINK_LIBS
   +              ${ARROW_PROTOBUF_LIBPROTOBUF}
                  STATIC_LINK_LIBS
                  arrow_flight_static)
    
   @@ -75,7 +79,6 @@ target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
    add_arrow_test(flight_sql_client_test
                   SOURCES
                   client_test.cc
   -               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
                   STATIC_LINK_LIBS
                   ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
                   LABELS
   @@ -85,7 +88,6 @@ add_arrow_test(flight_sql_server_test
                   SOURCES
                   server_test.cc
                   client_internal.cc
   -               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
                   STATIC_LINK_LIBS
                   ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
                   LABELS
   @@ -102,8 +104,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
                     example/sqlite_statement.cc
                     example/sqlite_statement_batch_reader.cc
                     example/sqlite_server.cc
   -                 example/sqlite_tables_schema_batch_reader.cc
   -                 "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
   +                 example/sqlite_tables_schema_batch_reader.cc)
      target_link_libraries(flight_sql_test_server
                            PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}
                                    ${SQLite3_LIBRARIES})
   diff --git a/cpp/vcpkg.json b/cpp/vcpkg.json
   index 11ce5250d..1aee71eb8 100644
   --- a/cpp/vcpkg.json
   +++ b/cpp/vcpkg.json
   @@ -17,7 +17,9 @@
        "benchmark",
        "boost-filesystem",
        "boost-multiprecision",
   +    "boost-process",
        "boost-system",
   +    "boost-uuid",
        "brotli",
        "bzip2",
        "c-ares",
   @@ -40,8 +42,5 @@
        "zlib",
        "zstd"
      ],
   -  "overrides": [
   -    { "name": "gtest", "version": "1.10.0", "port-version": 4 }
   -  ],
   -  "builtin-baseline": "b5865bfeba430cd44063fc54a45a8861195a715f"
   +  "builtin-baseline": "85b31152df8da18be5ec2b0dbd7b39b0d2404db4"
    }
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746044846



##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,251 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  virtual Status GetFlightInfo(const FlightCallOptions& options,
+                               const FlightDescriptor& descriptor,
+                               std::unique_ptr<FlightInfo>* info) {
+    return impl_->GetFlightInfo(options, descriptor, info);
+  }
+
+ protected:
+  virtual Status DoPut(const FlightCallOptions& options,
+                       const FlightDescriptor& descriptor,
+                       const std::shared_ptr<Schema>& schema,
+                       std::unique_ptr<FlightStreamWriter>* stream,
+                       std::unique_ptr<FlightMetadataReader>* reader) {
+    return impl_->DoPut(options, descriptor, schema, stream, reader);
+  }
+
+  virtual Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+                       std::unique_ptr<FlightStreamReader>* stream) {
+    return impl_->DoGet(options, ticket, stream);
+  }
+
+  virtual Status DoAction(const FlightCallOptions& options, const Action& action,
+                          std::unique_ptr<ResultStream>* results) {
+    return impl_->DoAction(options, action, results);
+  }
+};
+
+class PreparedStatement {

Review comment:
       ```suggestion
   class ARROW_EXPORT PreparedStatement {
   ```

##########
File path: cpp/src/arrow/flight/flight_sql/client_test.cc
##########
@@ -0,0 +1,494 @@
+// 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/client.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlClientMock : public FlightSqlClient {
+ public:
+  FlightSqlClientMock() : FlightSqlClient(nullptr) {}
+
+  ~FlightSqlClientMock() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+class TestFlightSqlClient : public ::testing::Test {
+ protected:
+  FlightSqlClientMock sql_client;
+  FlightCallOptions call_options;
+
+  void SetUp() override {}
+
+  void TearDown() override {}
+};
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST_F(TestFlightSqlClient, TestGetCatalogs) {
+  pb::sql::CommandGetCatalogs command;
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetCatalogs(call_options));
+}
+
+TEST_F(TestFlightSqlClient, TestGetSchemas) {
+  std::string schema_filter_pattern = "schema_filter_pattern";
+  std::string catalog = "catalog";
+
+  pb::sql::CommandGetSchemas command;
+  command.set_catalog(catalog);
+  command.set_schema_filter_pattern(schema_filter_pattern);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetSchemas(call_options, &catalog, &schema_filter_pattern));
+}
+
+TEST_F(TestFlightSqlClient, TestGetTables) {
+  std::string catalog = "catalog";
+  std::string schema_filter_pattern = "schema_filter_pattern";
+  std::string table_name_filter_pattern = "table_name_filter_pattern";
+  bool include_schema = true;
+  std::vector<std::string> table_types = {"type1", "type2"};
+
+  pb::sql::CommandGetTables command;
+  command.set_catalog(catalog);
+  command.set_schema_filter_pattern(schema_filter_pattern);
+  command.set_table_name_filter_pattern(table_name_filter_pattern);
+  command.set_include_schema(include_schema);
+  for (const std::string& table_type : table_types) {
+    command.add_table_types(table_type);
+  }
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetTables(call_options, &catalog, &schema_filter_pattern,
+                                 &table_name_filter_pattern, include_schema,
+                                 table_types));
+}
+
+TEST_F(TestFlightSqlClient, TestGetTableTypes) {
+  pb::sql::CommandGetTableTypes command;
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetTableTypes(call_options));
+}
+
+TEST_F(TestFlightSqlClient, TestGetExported) {
+  std::string catalog = "catalog";
+  std::string schema = "schema";
+  std::string table = "table";
+
+  pb::sql::CommandGetExportedKeys command;
+  command.set_catalog(catalog);
+  command.set_schema(schema);
+  command.set_table(table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetExportedKeys(call_options, &catalog, &schema, table));
+}
+
+TEST_F(TestFlightSqlClient, TestGetImported) {
+  std::string catalog = "catalog";
+  std::string schema = "schema";
+  std::string table = "table";
+
+  pb::sql::CommandGetImportedKeys command;
+  command.set_catalog(catalog);
+  command.set_schema(schema);
+  command.set_table(table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetImportedKeys(call_options, &catalog, &schema, table));
+}
+
+TEST_F(TestFlightSqlClient, TestGetPrimary) {
+  std::string catalog = "catalog";
+  std::string schema = "schema";
+  std::string table = "table";
+
+  pb::sql::CommandGetPrimaryKeys command;
+  command.set_catalog(catalog);
+  command.set_schema(schema);
+  command.set_table(table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetPrimaryKeys(call_options, &catalog, &schema, table));
+}
+
+TEST_F(TestFlightSqlClient, TestGetCrossReference) {
+  std::string pk_catalog = "pk_catalog";
+  std::string pk_schema = "pk_schema";
+  std::string pk_table = "pk_table";
+  std::string fk_catalog = "fk_catalog";
+  std::string fk_schema = "fk_schema";
+  std::string fk_table = "fk_table";
+
+  pb::sql::CommandGetCrossReference command;
+  command.set_pk_catalog(pk_catalog);
+  command.set_pk_schema(pk_schema);
+  command.set_pk_table(pk_table);
+  command.set_fk_catalog(fk_catalog);
+  command.set_fk_schema(fk_schema);
+  command.set_fk_table(fk_table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetCrossReference(call_options, &pk_catalog, &pk_schema, pk_table,
+                                         &fk_catalog, &fk_schema, fk_table));
+}
+
+TEST_F(TestFlightSqlClient, TestExecute) {
+  std::string query = "query";
+
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.Execute(call_options, query));
+}
+
+TEST_F(TestFlightSqlClient, TestPreparedStatementExecute) {
+  const std::string query = "query";
+
+  ON_CALL(sql_client, DoAction)
+      .WillByDefault([](const FlightCallOptions& options, const Action& action,
+                        std::unique_ptr<ResultStream>* results) {
+        google::protobuf::Any command;
+
+        pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+        prepared_statement_result.set_prepared_statement_handle("query");
+
+        command.PackFrom(prepared_statement_result);
+
+        *results = std::unique_ptr<ResultStream>(new SimpleResultStream(
+            {Result{Buffer::FromString(command.SerializeAsString())}}));
+
+        return Status::OK();
+      });
+
+  EXPECT_CALL(sql_client, DoAction(_, _, _)).Times(2);
+
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement, sql_client.Prepare(call_options, query));
+
+  EXPECT_CALL(sql_client, GetFlightInfo(_, _, _));
+
+  ASSERT_OK(prepared_statement->Execute());
+}
+
+TEST_F(TestFlightSqlClient, TestPreparedStatementExecuteParameterBinding) {
+  const std::string query = "query";
+
+  ON_CALL(sql_client, DoAction)
+      .WillByDefault([](const FlightCallOptions& options, const Action& action,
+                        std::unique_ptr<ResultStream>* results) {
+        google::protobuf::Any command;
+
+        pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+        prepared_statement_result.set_prepared_statement_handle("query");
+
+        auto schema = arrow::schema({arrow::field("id", int64())});
+
+        std::shared_ptr<Buffer> schema_buffer;
+        const arrow::Result<std::shared_ptr<Buffer>>& result =
+            arrow::ipc::SerializeSchema(*schema);
+
+        ARROW_ASSIGN_OR_RAISE(schema_buffer, result);
+
+        prepared_statement_result.set_parameter_schema(schema_buffer->ToString());
+
+        command.PackFrom(prepared_statement_result);
+
+        *results = std::unique_ptr<ResultStream>(new SimpleResultStream(
+            {Result{Buffer::FromString(command.SerializeAsString())}}));
+
+        return Status::OK();
+      });
+
+  std::shared_ptr<Buffer> buffer_ptr;
+  ON_CALL(sql_client, DoPut)
+      .WillByDefault([&buffer_ptr](const FlightCallOptions& options,
+                                   const FlightDescriptor& descriptor1,
+                                   const std::shared_ptr<Schema>& schema,
+                                   std::unique_ptr<FlightStreamWriter>* writer,
+                                   std::unique_ptr<FlightMetadataReader>* reader) {
+        writer->reset(new FlightStreamWriterMock());
+        reader->reset(new FlightMetadataReaderMock(&buffer_ptr));
+
+        return Status::OK();
+      });
+
+  EXPECT_CALL(sql_client, DoAction(_, _, _)).Times(2);
+  EXPECT_CALL(sql_client, DoPut(_, _, _, _, _));
+
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement, sql_client.Prepare(call_options, query));
+
+  auto parameter_schema = prepared_statement->parameter_schema();
+
+  arrow::Int64Builder int_builder;
+  ASSERT_OK(int_builder.Append(1));
+  std::shared_ptr<arrow::Array> int_array;
+  ASSERT_OK(int_builder.Finish(&int_array));
+  std::shared_ptr<arrow::RecordBatch> result;
+  result = arrow::RecordBatch::Make(parameter_schema, 1, {int_array});

Review comment:
       This can all be `auto result = RecordBatchFromJSON(parameter_schema, "[[1]]");`

##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_server.cc
##########
@@ -0,0 +1,676 @@
+// 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/api.h>
+#include <arrow/flight/flight_sql/example/sqlite_server.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h>
+#include <arrow/flight/flight_sql/example/sqlite_tables_schema_batch_reader.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const GetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.catalog.has_value()) {
+    table_query << " and catalog_name='" << command.catalog.value() << "'";
+  }
+
+  if (command.schema_filter_pattern.has_value()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern.value()
+                << "'";
+  }
+
+  if (command.table_name_filter_pattern.has_value()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern.value()
+                << "'";
+  }
+
+  if (!command.table_types.empty()) {
+    table_query << " and table_type IN (";
+    size_t size = command.table_types.size();
+    for (size_t i = 0; i < size; i++) {
+      table_query << "'" << command.table_types[i] << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt, FlightMessageReader* reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = static_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = static_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = static_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer = static_cast<StringScalar&>(*holder).value;
+            sqlite3_bind_text(stmt, c + 1, reinterpret_cast<const char*>(buffer->data()),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer = static_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer(sqlite3* db) : db_(db), uuid_generator_({}) {
+  assert(db_);
+}
+
+arrow::Result<std::shared_ptr<SQLiteFlightSqlServer>> SQLiteFlightSqlServer::Create() {
+  sqlite3* db = nullptr;
+
+  if (sqlite3_open(":memory:", &db)) {
+    std::string err_msg = "Can't open database: ";
+    if (db != nullptr) {
+      err_msg += sqlite3_errmsg(db);
+      sqlite3_close(db);
+    } else {
+      err_msg += "Unable to start SQLite. Insufficient memory";
+    }
+
+    return Status::RError(err_msg);
+  }
+
+  std::shared_ptr<SQLiteFlightSqlServer> result(new SQLiteFlightSqlServer(db));

Review comment:
       std::make_shared?

##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       Does the fix I posted work for you? https://github.com/apache/arrow/pull/11507#discussion_r743911807

##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})

Review comment:
       ARROW_FLIGHT_TEST_LINK_LIBS isn't used anywhere.

##########
File path: cpp/vcpkg.json
##########
@@ -34,6 +34,7 @@
     "rapidjson",
     "re2",
     "snappy",
+    "sqlite3",

Review comment:
       N.B. in my experimentation I found that `boost-process` and `boost-uuid` are also required now.

##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,251 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  virtual Status GetFlightInfo(const FlightCallOptions& options,

Review comment:
       Was this meant to be public?

##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,251 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types);

Review comment:
       ```suggestion
         bool include_schema, const std::vector<std::string>& table_types);
   ```

##########
File path: cpp/src/arrow/flight/flight_sql/client.cc
##########
@@ -0,0 +1,432 @@
+// 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/buffer.h>

Review comment:
       Note we usually use "" includes for arrow headers, also, the arrow includes are ordered after any third party includes (I believe the linter will do this automatically so long as quotes are used)

##########
File path: cpp/src/arrow/flight/flight_sql/test_app_cli.cc
##########
@@ -0,0 +1,192 @@
+// 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/array/builder_binary.h>
+#include <arrow/array/builder_primitive.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight_sql/api.h>
+#include <arrow/io/memory.h>
+#include <arrow/pretty_print.h>
+#include <arrow/status.h>
+#include <arrow/table.h>
+#include <gflags/gflags.h>
+
+#include <boost/algorithm/string.hpp>
+#include <iostream>
+#include <memory>
+
+using arrow::Result;
+using arrow::Schema;
+using arrow::Status;
+using arrow::flight::ClientAuthHandler;
+using arrow::flight::FlightCallOptions;
+using arrow::flight::FlightClient;
+using arrow::flight::FlightDescriptor;
+using arrow::flight::FlightEndpoint;
+using arrow::flight::FlightInfo;
+using arrow::flight::FlightStreamChunk;
+using arrow::flight::FlightStreamReader;
+using arrow::flight::Location;
+using arrow::flight::Ticket;
+using arrow::flight::sql::FlightSqlClient;
+
+DEFINE_string(host, "localhost", "Host to connect to");
+DEFINE_int32(port, 32010, "Port to connect to");
+DEFINE_string(username, "", "Username");
+DEFINE_string(password, "", "Password");
+
+DEFINE_string(command, "", "Method to run");
+DEFINE_string(query, "", "Query");
+DEFINE_string(catalog, "", "Catalog");
+DEFINE_string(schema, "", "Schema");
+DEFINE_string(table, "", "Table");
+
+Status PrintResultsForEndpoint(FlightSqlClient& client,
+                               const FlightCallOptions& call_options,
+                               const FlightEndpoint& endpoint) {
+  ARROW_ASSIGN_OR_RAISE(auto stream, client.DoGet(call_options, endpoint.ticket));
+
+  const arrow::Result<std::shared_ptr<Schema>>& schema = stream->GetSchema();
+  ARROW_RETURN_NOT_OK(schema);
+
+  std::cout << "Schema:" << std::endl;
+  std::cout << schema->get()->ToString() << std::endl << std::endl;
+
+  std::cout << "Results:" << std::endl;
+
+  FlightStreamChunk chunk;
+  int64_t num_rows = 0;
+
+  while (true) {
+    ARROW_RETURN_NOT_OK(stream->Next(&chunk));
+    if (!(chunk.data != nullptr)) {

Review comment:
       ```suggestion
       if (!chunk.data) {
   ```

##########
File path: cpp/src/arrow/flight/flight_sql/server.cc
##########
@@ -0,0 +1,663 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include <arrow/api.h>
+#include <arrow/buffer.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <google/protobuf/any.pb.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <sstream>
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+std::string FlightSqlServerBase::CreateStatementQueryTicket(

Review comment:
       If this doesn't need any state from the class, can it be made a helper function instead of a method instead? (Just to reduce the amount of stuff exposed in the header.)

##########
File path: cpp/src/arrow/flight/flight_sql/server.h
##########
@@ -0,0 +1,480 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <arrow/flight/server.h>
+#include <arrow/util/optional.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  // TODO: To be implemented.
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;
+  util::optional<std::string> fk_catalog;
+  util::optional<std::string> fk_schema;
+  std::string fk_table;
+};
+
+struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+class ARROW_EXPORT FlightSqlServerBase : public FlightServerBase {
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType kCreatePreparedStatementActionType =
+      ActionType{"CreatePreparedStatement",
+                 "Creates a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionCreatePreparedStatementRequest\n"
+                 "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType kClosePreparedStatementActionType =
+      ActionType{"ClosePreparedStatement",
+                 "Closes a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionClosePreparedStatementRequest\n"
+                 "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] command      The StatementQuery object containing the SQL statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const StatementQuery& command,
+                                        const ServerCallContext& context,

Review comment:
       Sorry I didn't notice this earlier, but for these methods, can we keep the argument order consistent with the base server class? That is, put the ServerCallContext first?

##########
File path: cpp/src/arrow/flight/flight_sql/client_test.cc
##########
@@ -0,0 +1,494 @@
+// 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/client.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlClientMock : public FlightSqlClient {
+ public:
+  FlightSqlClientMock() : FlightSqlClient(nullptr) {}
+
+  ~FlightSqlClientMock() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+class TestFlightSqlClient : public ::testing::Test {
+ protected:
+  FlightSqlClientMock sql_client;
+  FlightCallOptions call_options;
+
+  void SetUp() override {}
+
+  void TearDown() override {}
+};
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST_F(TestFlightSqlClient, TestGetCatalogs) {
+  pb::sql::CommandGetCatalogs command;
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetCatalogs(call_options));
+}
+
+TEST_F(TestFlightSqlClient, TestGetSchemas) {
+  std::string schema_filter_pattern = "schema_filter_pattern";
+  std::string catalog = "catalog";
+
+  pb::sql::CommandGetSchemas command;
+  command.set_catalog(catalog);
+  command.set_schema_filter_pattern(schema_filter_pattern);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetSchemas(call_options, &catalog, &schema_filter_pattern));
+}
+
+TEST_F(TestFlightSqlClient, TestGetTables) {
+  std::string catalog = "catalog";
+  std::string schema_filter_pattern = "schema_filter_pattern";
+  std::string table_name_filter_pattern = "table_name_filter_pattern";
+  bool include_schema = true;
+  std::vector<std::string> table_types = {"type1", "type2"};
+
+  pb::sql::CommandGetTables command;
+  command.set_catalog(catalog);
+  command.set_schema_filter_pattern(schema_filter_pattern);
+  command.set_table_name_filter_pattern(table_name_filter_pattern);
+  command.set_include_schema(include_schema);
+  for (const std::string& table_type : table_types) {
+    command.add_table_types(table_type);
+  }
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetTables(call_options, &catalog, &schema_filter_pattern,
+                                 &table_name_filter_pattern, include_schema,
+                                 table_types));
+}
+
+TEST_F(TestFlightSqlClient, TestGetTableTypes) {
+  pb::sql::CommandGetTableTypes command;
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetTableTypes(call_options));
+}
+
+TEST_F(TestFlightSqlClient, TestGetExported) {
+  std::string catalog = "catalog";
+  std::string schema = "schema";
+  std::string table = "table";
+
+  pb::sql::CommandGetExportedKeys command;
+  command.set_catalog(catalog);
+  command.set_schema(schema);
+  command.set_table(table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetExportedKeys(call_options, &catalog, &schema, table));
+}
+
+TEST_F(TestFlightSqlClient, TestGetImported) {
+  std::string catalog = "catalog";
+  std::string schema = "schema";
+  std::string table = "table";
+
+  pb::sql::CommandGetImportedKeys command;
+  command.set_catalog(catalog);
+  command.set_schema(schema);
+  command.set_table(table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetImportedKeys(call_options, &catalog, &schema, table));
+}
+
+TEST_F(TestFlightSqlClient, TestGetPrimary) {
+  std::string catalog = "catalog";
+  std::string schema = "schema";
+  std::string table = "table";
+
+  pb::sql::CommandGetPrimaryKeys command;
+  command.set_catalog(catalog);
+  command.set_schema(schema);
+  command.set_table(table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetPrimaryKeys(call_options, &catalog, &schema, table));
+}
+
+TEST_F(TestFlightSqlClient, TestGetCrossReference) {
+  std::string pk_catalog = "pk_catalog";
+  std::string pk_schema = "pk_schema";
+  std::string pk_table = "pk_table";
+  std::string fk_catalog = "fk_catalog";
+  std::string fk_schema = "fk_schema";
+  std::string fk_table = "fk_table";
+
+  pb::sql::CommandGetCrossReference command;
+  command.set_pk_catalog(pk_catalog);
+  command.set_pk_schema(pk_schema);
+  command.set_pk_table(pk_table);
+  command.set_fk_catalog(fk_catalog);
+  command.set_fk_schema(fk_schema);
+  command.set_fk_table(fk_table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetCrossReference(call_options, &pk_catalog, &pk_schema, pk_table,
+                                         &fk_catalog, &fk_schema, fk_table));
+}
+
+TEST_F(TestFlightSqlClient, TestExecute) {
+  std::string query = "query";
+
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.Execute(call_options, query));
+}
+
+TEST_F(TestFlightSqlClient, TestPreparedStatementExecute) {
+  const std::string query = "query";
+
+  ON_CALL(sql_client, DoAction)
+      .WillByDefault([](const FlightCallOptions& options, const Action& action,
+                        std::unique_ptr<ResultStream>* results) {
+        google::protobuf::Any command;
+
+        pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+        prepared_statement_result.set_prepared_statement_handle("query");
+
+        command.PackFrom(prepared_statement_result);
+
+        *results = std::unique_ptr<ResultStream>(new SimpleResultStream(
+            {Result{Buffer::FromString(command.SerializeAsString())}}));
+
+        return Status::OK();
+      });
+
+  EXPECT_CALL(sql_client, DoAction(_, _, _)).Times(2);
+
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement, sql_client.Prepare(call_options, query));
+
+  EXPECT_CALL(sql_client, GetFlightInfo(_, _, _));
+
+  ASSERT_OK(prepared_statement->Execute());
+}
+
+TEST_F(TestFlightSqlClient, TestPreparedStatementExecuteParameterBinding) {
+  const std::string query = "query";
+
+  ON_CALL(sql_client, DoAction)
+      .WillByDefault([](const FlightCallOptions& options, const Action& action,
+                        std::unique_ptr<ResultStream>* results) {
+        google::protobuf::Any command;
+
+        pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+        prepared_statement_result.set_prepared_statement_handle("query");
+
+        auto schema = arrow::schema({arrow::field("id", int64())});
+
+        std::shared_ptr<Buffer> schema_buffer;
+        const arrow::Result<std::shared_ptr<Buffer>>& result =
+            arrow::ipc::SerializeSchema(*schema);
+
+        ARROW_ASSIGN_OR_RAISE(schema_buffer, result);
+
+        prepared_statement_result.set_parameter_schema(schema_buffer->ToString());
+
+        command.PackFrom(prepared_statement_result);
+
+        *results = std::unique_ptr<ResultStream>(new SimpleResultStream(
+            {Result{Buffer::FromString(command.SerializeAsString())}}));
+
+        return Status::OK();
+      });
+
+  std::shared_ptr<Buffer> buffer_ptr;
+  ON_CALL(sql_client, DoPut)
+      .WillByDefault([&buffer_ptr](const FlightCallOptions& options,
+                                   const FlightDescriptor& descriptor1,
+                                   const std::shared_ptr<Schema>& schema,
+                                   std::unique_ptr<FlightStreamWriter>* writer,
+                                   std::unique_ptr<FlightMetadataReader>* reader) {
+        writer->reset(new FlightStreamWriterMock());
+        reader->reset(new FlightMetadataReaderMock(&buffer_ptr));
+
+        return Status::OK();
+      });
+
+  EXPECT_CALL(sql_client, DoAction(_, _, _)).Times(2);
+  EXPECT_CALL(sql_client, DoPut(_, _, _, _, _));
+
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement, sql_client.Prepare(call_options, query));
+
+  auto parameter_schema = prepared_statement->parameter_schema();
+
+  arrow::Int64Builder int_builder;
+  ASSERT_OK(int_builder.Append(1));
+  std::shared_ptr<arrow::Array> int_array;
+  ASSERT_OK(int_builder.Finish(&int_array));
+  std::shared_ptr<arrow::RecordBatch> result;
+  result = arrow::RecordBatch::Make(parameter_schema, 1, {int_array});
+  ASSERT_OK(prepared_statement->SetParameters(result));
+
+  EXPECT_CALL(sql_client, GetFlightInfo(_, _, _));
+
+  ASSERT_OK(prepared_statement->Execute());
+}
+
+TEST_F(TestFlightSqlClient, TestExecuteUpdate) {
+  std::string query = "query";
+
+  pb::sql::CommandStatementUpdate command;
+
+  command.set_query(query);
+
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const FlightDescriptor& descriptor = FlightDescriptor::Command(any.SerializeAsString());
+
+  pb::sql::DoPutUpdateResult doPutUpdateResult;
+  doPutUpdateResult.set_record_count(100);
+  const std::string& string = doPutUpdateResult.SerializeAsString();
+
+  auto buffer_ptr = std::make_shared<Buffer>(
+      reinterpret_cast<const uint8_t*>(string.data()), doPutUpdateResult.ByteSizeLong());
+
+  ON_CALL(sql_client, DoPut)
+      .WillByDefault([&buffer_ptr](const FlightCallOptions& options,
+                                   const FlightDescriptor& descriptor1,
+                                   const std::shared_ptr<Schema>& schema,
+                                   std::unique_ptr<FlightStreamWriter>* writer,
+                                   std::unique_ptr<FlightMetadataReader>* reader) {
+        reader->reset(new FlightMetadataReaderMock(&buffer_ptr));
+
+        return Status::OK();
+      });
+
+  std::unique_ptr<FlightInfo> flight_info;
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+  EXPECT_CALL(sql_client, DoPut(Ref(call_options), descriptor, _, _, _));
+
+  ASSERT_OK_AND_ASSIGN(auto num_rows, sql_client.ExecuteUpdate(call_options, query));
+
+  ASSERT_EQ(num_rows, 100);
+}
+
+TEST_F(TestFlightSqlClient, TestGetSqlInfo) {
+  std::vector<int> sql_info{pb::sql::SqlInfo::FLIGHT_SQL_SERVER_NAME,
+                            pb::sql::SqlInfo::FLIGHT_SQL_SERVER_VERSION,
+                            pb::sql::SqlInfo::FLIGHT_SQL_SERVER_ARROW_VERSION};
+  pb::sql::CommandGetSqlInfo command;
+
+  for (const auto& info : sql_info) command.add_info(info);
+  google::protobuf::Any any;
+  any.PackFrom(command);
+  const FlightDescriptor& descriptor = FlightDescriptor::Command(any.SerializeAsString());
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+  ASSERT_OK(sql_client.GetSqlInfo(call_options, sql_info));
+}
+
+template <class Func>
+inline void AssertTestPreparedStatementExecuteUpdateOk(
+    Func func, const std::shared_ptr<Schema>* schema, FlightSqlClientMock& sql_client) {
+  const std::string query = "SELECT * FROM IRRELEVANT";
+  int64_t expected_rows = 100L;
+  pb::sql::DoPutUpdateResult result;
+  result.set_record_count(expected_rows);
+
+  ON_CALL(sql_client, DoAction)
+      .WillByDefault([&query, &schema](const FlightCallOptions& options,
+                                       const Action& action,
+                                       std::unique_ptr<ResultStream>* results) {
+        google::protobuf::Any command;
+        pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+        prepared_statement_result.set_prepared_statement_handle(query);
+
+        if (schema != NULLPTR) {
+          std::shared_ptr<Buffer> schema_buffer;
+          const arrow::Result<std::shared_ptr<Buffer>>& result =
+              arrow::ipc::SerializeSchema(**schema);
+
+          ARROW_ASSIGN_OR_RAISE(schema_buffer, result);
+          prepared_statement_result.set_parameter_schema(schema_buffer->ToString());
+        }
+
+        command.PackFrom(prepared_statement_result);
+        *results = std::unique_ptr<ResultStream>(new SimpleResultStream(
+            {Result{Buffer::FromString(command.SerializeAsString())}}));
+
+        return Status::OK();
+      });
+  EXPECT_CALL(sql_client, DoAction(_, _, _)).Times(2);
+
+  auto buffer = Buffer::FromString(result.SerializeAsString());
+  ON_CALL(sql_client, DoPut)
+      .WillByDefault([&buffer](const FlightCallOptions& options,
+                               const FlightDescriptor& descriptor1,
+                               const std::shared_ptr<Schema>& schema,
+                               std::unique_ptr<FlightStreamWriter>* writer,
+                               std::unique_ptr<FlightMetadataReader>* reader) {
+        reader->reset(new FlightMetadataReaderMock(&buffer));
+        writer->reset(new FlightStreamWriterMock());
+        return Status::OK();
+      });
+  if (schema == NULLPTR) {
+    EXPECT_CALL(sql_client, DoPut(_, _, _, _, _));
+  } else {
+    EXPECT_CALL(sql_client, DoPut(_, _, *schema, _, _));
+  }
+
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement, sql_client.Prepare({}, query));
+  func(prepared_statement, sql_client, schema, expected_rows);
+  ASSERT_OK_AND_ASSIGN(auto rows, prepared_statement->ExecuteUpdate());
+  ASSERT_EQ(expected_rows, rows);
+}
+
+TEST_F(TestFlightSqlClient, TestPreparedStatementExecuteUpdateNoParameterBinding) {
+  AssertTestPreparedStatementExecuteUpdateOk(
+      [](const std::shared_ptr<PreparedStatement>& prepared_statement,
+         FlightSqlClient& sql_client, const std::shared_ptr<Schema>* schema,
+         const int64_t& row_count) {},
+      NULLPTR, sql_client);
+}
+
+TEST_F(TestFlightSqlClient, TestPreparedStatementExecuteUpdateWithParameterBinding) {
+  const auto schema = arrow::schema(
+      {arrow::field("field0", arrow::utf8()), arrow::field("field1", arrow::uint8())});
+  AssertTestPreparedStatementExecuteUpdateOk(
+      [](const std::shared_ptr<PreparedStatement>& prepared_statement,
+         FlightSqlClient& sql_client, const std::shared_ptr<Schema>* schema,
+         const int64_t& row_count) {
+        std::shared_ptr<Array> string_array;
+        std::shared_ptr<Array> uint8_array;
+        const std::vector<std::string> string_data{"Lorem", "Ipsum", "Foo", "Bar", "Baz"};
+        const std::vector<uint8_t> uint8_data{0, 10, 15, 20, 25};
+        ArrayFromVector<StringType, std::string>(string_data, &string_array);
+        ArrayFromVector<UInt8Type, uint8_t>(uint8_data, &uint8_array);
+        std::shared_ptr<RecordBatch> recordBatch =
+            RecordBatch::Make(*schema, row_count, {string_array, uint8_array});

Review comment:
       Similarly this all could use RecordBatchFromJSON though you could also do `auto string_array = ArrayFromJSON(utf8(), R"(["Lorem", "Ipsum", ...])");` and so on.

##########
File path: cpp/src/arrow/flight/flight_sql/server.cc
##########
@@ -0,0 +1,663 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include <arrow/api.h>
+#include <arrow/buffer.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <google/protobuf/any.pb.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <sstream>
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+std::string FlightSqlServerBase::CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  const std::string& ticket_string = ticket.SerializeAsString();

Review comment:
       Can we use SerializeToString and handle the potential error there, instead of this (which silently returns an empty string)?

##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,251 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  virtual Status GetFlightInfo(const FlightCallOptions& options,
+                               const FlightDescriptor& descriptor,
+                               std::unique_ptr<FlightInfo>* info) {
+    return impl_->GetFlightInfo(options, descriptor, info);
+  }
+
+ protected:
+  virtual Status DoPut(const FlightCallOptions& options,
+                       const FlightDescriptor& descriptor,
+                       const std::shared_ptr<Schema>& schema,
+                       std::unique_ptr<FlightStreamWriter>* stream,
+                       std::unique_ptr<FlightMetadataReader>* reader) {
+    return impl_->DoPut(options, descriptor, schema, stream, reader);
+  }
+
+  virtual Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+                       std::unique_ptr<FlightStreamReader>* stream) {
+    return impl_->DoGet(options, ticket, stream);
+  }
+
+  virtual Status DoAction(const FlightCallOptions& options, const Action& action,
+                          std::unique_ptr<ResultStream>* results) {
+    return impl_->DoAction(options, action, results);
+  }
+};
+
+class PreparedStatement {

Review comment:
       Can we also add a docstring?

##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_server.cc
##########
@@ -0,0 +1,676 @@
+// 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/api.h>
+#include <arrow/flight/flight_sql/example/sqlite_server.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h>
+#include <arrow/flight/flight_sql/example/sqlite_tables_schema_batch_reader.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const GetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.catalog.has_value()) {
+    table_query << " and catalog_name='" << command.catalog.value() << "'";
+  }
+
+  if (command.schema_filter_pattern.has_value()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern.value()
+                << "'";
+  }
+
+  if (command.table_name_filter_pattern.has_value()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern.value()
+                << "'";
+  }
+
+  if (!command.table_types.empty()) {
+    table_query << " and table_type IN (";
+    size_t size = command.table_types.size();
+    for (size_t i = 0; i < size; i++) {
+      table_query << "'" << command.table_types[i] << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt, FlightMessageReader* reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = static_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = static_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = static_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer = static_cast<StringScalar&>(*holder).value;
+            sqlite3_bind_text(stmt, c + 1, reinterpret_cast<const char*>(buffer->data()),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer = static_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer(sqlite3* db) : db_(db), uuid_generator_({}) {
+  assert(db_);
+}
+
+arrow::Result<std::shared_ptr<SQLiteFlightSqlServer>> SQLiteFlightSqlServer::Create() {
+  sqlite3* db = nullptr;
+
+  if (sqlite3_open(":memory:", &db)) {
+    std::string err_msg = "Can't open database: ";
+    if (db != nullptr) {
+      err_msg += sqlite3_errmsg(db);
+      sqlite3_close(db);
+    } else {
+      err_msg += "Unable to start SQLite. Insufficient memory";
+    }
+
+    return Status::RError(err_msg);

Review comment:
       Status::Invalid?

##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_statement.cc
##########
@@ -0,0 +1,138 @@
+// 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/flight_sql/example/sqlite_server.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetDataTypeFromSqliteType(const int column_type) {
+  switch (column_type) {
+    case SQLITE_INTEGER:
+      return int64();
+    case SQLITE_FLOAT:
+      return float64();
+    case SQLITE_BLOB:
+      return binary();
+    case SQLITE_TEXT:
+      return utf8();
+    case SQLITE_NULL:
+    default:
+      return null();
+  }
+}
+
+arrow::Result<std::shared_ptr<SqliteStatement>> SqliteStatement::Create(
+    sqlite3* db, const std::string& sql) {
+  sqlite3_stmt* stmt = nullptr;
+  int rc =
+      sqlite3_prepare_v2(db, sql.c_str(), static_cast<int>(sql.size()), &stmt, NULLPTR);
+
+  if (rc != SQLITE_OK) {
+    std::string err_msg = "Can't prepare statement: " + std::string(sqlite3_errmsg(db));
+    if (stmt != nullptr) {
+      rc = sqlite3_finalize(stmt);
+      if (rc != SQLITE_OK) {
+        err_msg += "; Failed to finalize SQLite statement: ";
+        err_msg += std::string(sqlite3_errmsg(db));
+      }
+    }
+    return Status::RError(err_msg);

Review comment:
       Status::Invalid? RError is for R.

##########
File path: cpp/src/arrow/flight/flight_sql/server_test.cc
##########
@@ -0,0 +1,663 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/api.h>
+#include <arrow/flight/flight_sql/example/sqlite_server.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+std::unique_ptr<TestServer> server;
+std::unique_ptr<FlightSqlClient> sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server.reset(new TestServer("flight_sql_test_server"));
+    server->Start();
+    for (int i = 0; i < 100; i++) {
+      std::this_thread::sleep_for(std::chrono::milliseconds(10));
+      if (server->IsRunning()) {
+        break;
+      }
+    }
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+    server->Stop();
+    server.reset();
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array;
+  std::shared_ptr<Array> keyname_array;
+  std::shared_ptr<Array> value_array;
+  std::shared_ptr<Array> foreignId_array;
+  ArrayFromVector<Int64Type, std::int64_t>({1, 2, 3}, &id_array);
+  ArrayFromVector<StringType, std::string>({"one", "zero", "negative one"},
+                                           &keyname_array);
+  ArrayFromVector<Int64Type, std::int64_t>({1, 0, -1}, &value_array);
+  ArrayFromVector<Int64Type, std::int64_t>({1, 1, 1}, &foreignId_array);

Review comment:
       As mentioned, ArrayFromJSON/RecordBatchFromJSON/TableFromJSON can help clean up a lot of this.

##########
File path: cpp/src/arrow/flight/flight_sql/server_test.cc
##########
@@ -0,0 +1,663 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/api.h>
+#include <arrow/flight/flight_sql/example/sqlite_server.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+std::unique_ptr<TestServer> server;
+std::unique_ptr<FlightSqlClient> sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server.reset(new TestServer("flight_sql_test_server"));
+    server->Start();
+    for (int i = 0; i < 100; i++) {
+      std::this_thread::sleep_for(std::chrono::milliseconds(10));
+      if (server->IsRunning()) {
+        break;
+      }
+    }
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+    server->Stop();
+    server.reset();
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array;
+  std::shared_ptr<Array> keyname_array;
+  std::shared_ptr<Array> value_array;
+  std::shared_ptr<Array> foreignId_array;
+  ArrayFromVector<Int64Type, std::int64_t>({1, 2, 3}, &id_array);
+  ArrayFromVector<StringType, std::string>({"one", "zero", "negative one"},
+                                           &keyname_array);
+  ArrayFromVector<Int64Type, std::int64_t>({1, 0, -1}, &value_array);
+  ArrayFromVector<Int64Type, std::int64_t>({1, 1, 1}, &foreignId_array);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::vector<std::string> table_types;
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {"foreignTable", "intTable", "sqlite_sequence"}, &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableFilter) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableTypesFilter) {
+  std::vector<std::string> table_types{"index"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_TRUE(table->schema()->Equals(SqlSchema::GetTablesSchema()));
+
+  ASSERT_EQ(table->num_rows(), 0);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithUnexistenceTableTypeFilter) {
+  std::vector<std::string> table_types{"table"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {
+          "foreignTable",
+          "intTable",
+          "sqlite_sequence",
+      },
+      &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithIncludedSchemas) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             true, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Schema> schema_table =
+      arrow::schema({arrow::field("id", int64(), true, NULL),

Review comment:
       nit: use nullptr over null (or just omit the argument)?

##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,251 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  virtual Status GetFlightInfo(const FlightCallOptions& options,
+                               const FlightDescriptor& descriptor,
+                               std::unique_ptr<FlightInfo>* info) {
+    return impl_->GetFlightInfo(options, descriptor, info);
+  }
+
+ protected:
+  virtual Status DoPut(const FlightCallOptions& options,
+                       const FlightDescriptor& descriptor,
+                       const std::shared_ptr<Schema>& schema,
+                       std::unique_ptr<FlightStreamWriter>* stream,
+                       std::unique_ptr<FlightMetadataReader>* reader) {
+    return impl_->DoPut(options, descriptor, schema, stream, reader);
+  }
+
+  virtual Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+                       std::unique_ptr<FlightStreamReader>* stream) {
+    return impl_->DoGet(options, ticket, stream);
+  }
+
+  virtual Status DoAction(const FlightCallOptions& options, const Action& action,
+                          std::unique_ptr<ResultStream>* results) {
+    return impl_->DoAction(options, action, results);
+  }
+};
+
+class PreparedStatement {
+  FlightSqlClient& client_;
+  FlightCallOptions options_;
+  std::string handle_;
+  std::shared_ptr<Schema> dataset_schema_;
+  std::shared_ptr<Schema> parameter_schema_;
+  std::shared_ptr<RecordBatch> parameter_binding_;
+  bool is_closed_;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client                Client object used to make the RPC requests.
+  /// \param[in] handle                Handle for this prepared statement.
+  /// \param[in] dataset_schema        Schema of the resulting dataset.
+  /// \param[in] parameter_schema      Schema of the parameters (if any).
+  /// \param[in] options               RPC-layer hints for this call.
+  PreparedStatement(FlightSqlClient& client, std::string handle,

Review comment:
       By convention, Arrow prefers pointers over mutable references for this sort of thing.

##########
File path: cpp/src/arrow/flight/flight_sql/server.h
##########
@@ -0,0 +1,480 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <arrow/flight/server.h>
+#include <arrow/util/optional.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  // TODO: To be implemented.

Review comment:
       Do we want to file a JIRA or do you plan to take care of this?

##########
File path: cpp/src/arrow/flight/flight_sql/client.cc
##########
@@ -0,0 +1,432 @@
+// 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/buffer.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/result.h>
+#include <arrow/testing/gtest_util.h>
+#include <arrow/util/logging.h>
+#include <google/protobuf/any.pb.h>
+
+namespace pb = arrow::flight::protocol;

Review comment:
       IIRC, some versions of protobuf define their own `namespace pb` so a different alias may be preferable

##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_server.cc
##########
@@ -0,0 +1,676 @@
+// 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/api.h>
+#include <arrow/flight/flight_sql/example/sqlite_server.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h>
+#include <arrow/flight/flight_sql/example/sqlite_tables_schema_batch_reader.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const GetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.catalog.has_value()) {
+    table_query << " and catalog_name='" << command.catalog.value() << "'";
+  }
+
+  if (command.schema_filter_pattern.has_value()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern.value()
+                << "'";
+  }
+
+  if (command.table_name_filter_pattern.has_value()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern.value()
+                << "'";
+  }
+
+  if (!command.table_types.empty()) {
+    table_query << " and table_type IN (";
+    size_t size = command.table_types.size();
+    for (size_t i = 0; i < size; i++) {
+      table_query << "'" << command.table_types[i] << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt, FlightMessageReader* reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = static_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = static_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = static_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer = static_cast<StringScalar&>(*holder).value;
+            sqlite3_bind_text(stmt, c + 1, reinterpret_cast<const char*>(buffer->data()),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer = static_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer(sqlite3* db) : db_(db), uuid_generator_({}) {
+  assert(db_);
+}
+
+arrow::Result<std::shared_ptr<SQLiteFlightSqlServer>> SQLiteFlightSqlServer::Create() {
+  sqlite3* db = nullptr;
+
+  if (sqlite3_open(":memory:", &db)) {
+    std::string err_msg = "Can't open database: ";
+    if (db != nullptr) {
+      err_msg += sqlite3_errmsg(db);
+      sqlite3_close(db);
+    } else {
+      err_msg += "Unable to start SQLite. Insufficient memory";
+    }
+
+    return Status::RError(err_msg);
+  }
+
+  std::shared_ptr<SQLiteFlightSqlServer> result(new SQLiteFlightSqlServer(db));
+
+  ARROW_UNUSED(result->ExecuteSql(R"(

Review comment:
       Why ARROW_UNUSED? We can return the status here.

##########
File path: cpp/src/arrow/flight/flight_sql/client_test.cc
##########
@@ -0,0 +1,494 @@
+// 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/client.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class FlightSqlClientMock : public FlightSqlClient {
+ public:
+  FlightSqlClientMock() : FlightSqlClient(nullptr) {}
+
+  ~FlightSqlClientMock() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+class TestFlightSqlClient : public ::testing::Test {
+ protected:
+  FlightSqlClientMock sql_client;
+  FlightCallOptions call_options;
+
+  void SetUp() override {}
+
+  void TearDown() override {}
+};
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST_F(TestFlightSqlClient, TestGetCatalogs) {
+  pb::sql::CommandGetCatalogs command;
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetCatalogs(call_options));
+}
+
+TEST_F(TestFlightSqlClient, TestGetSchemas) {
+  std::string schema_filter_pattern = "schema_filter_pattern";
+  std::string catalog = "catalog";
+
+  pb::sql::CommandGetSchemas command;
+  command.set_catalog(catalog);
+  command.set_schema_filter_pattern(schema_filter_pattern);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetSchemas(call_options, &catalog, &schema_filter_pattern));
+}
+
+TEST_F(TestFlightSqlClient, TestGetTables) {
+  std::string catalog = "catalog";
+  std::string schema_filter_pattern = "schema_filter_pattern";
+  std::string table_name_filter_pattern = "table_name_filter_pattern";
+  bool include_schema = true;
+  std::vector<std::string> table_types = {"type1", "type2"};
+
+  pb::sql::CommandGetTables command;
+  command.set_catalog(catalog);
+  command.set_schema_filter_pattern(schema_filter_pattern);
+  command.set_table_name_filter_pattern(table_name_filter_pattern);
+  command.set_include_schema(include_schema);
+  for (const std::string& table_type : table_types) {
+    command.add_table_types(table_type);
+  }
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetTables(call_options, &catalog, &schema_filter_pattern,
+                                 &table_name_filter_pattern, include_schema,
+                                 table_types));
+}
+
+TEST_F(TestFlightSqlClient, TestGetTableTypes) {
+  pb::sql::CommandGetTableTypes command;
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetTableTypes(call_options));
+}
+
+TEST_F(TestFlightSqlClient, TestGetExported) {
+  std::string catalog = "catalog";
+  std::string schema = "schema";
+  std::string table = "table";
+
+  pb::sql::CommandGetExportedKeys command;
+  command.set_catalog(catalog);
+  command.set_schema(schema);
+  command.set_table(table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetExportedKeys(call_options, &catalog, &schema, table));
+}
+
+TEST_F(TestFlightSqlClient, TestGetImported) {
+  std::string catalog = "catalog";
+  std::string schema = "schema";
+  std::string table = "table";
+
+  pb::sql::CommandGetImportedKeys command;
+  command.set_catalog(catalog);
+  command.set_schema(schema);
+  command.set_table(table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetImportedKeys(call_options, &catalog, &schema, table));
+}
+
+TEST_F(TestFlightSqlClient, TestGetPrimary) {
+  std::string catalog = "catalog";
+  std::string schema = "schema";
+  std::string table = "table";
+
+  pb::sql::CommandGetPrimaryKeys command;
+  command.set_catalog(catalog);
+  command.set_schema(schema);
+  command.set_table(table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetPrimaryKeys(call_options, &catalog, &schema, table));
+}
+
+TEST_F(TestFlightSqlClient, TestGetCrossReference) {
+  std::string pk_catalog = "pk_catalog";
+  std::string pk_schema = "pk_schema";
+  std::string pk_table = "pk_table";
+  std::string fk_catalog = "fk_catalog";
+  std::string fk_schema = "fk_schema";
+  std::string fk_table = "fk_table";
+
+  pb::sql::CommandGetCrossReference command;
+  command.set_pk_catalog(pk_catalog);
+  command.set_pk_schema(pk_schema);
+  command.set_pk_table(pk_table);
+  command.set_fk_catalog(fk_catalog);
+  command.set_fk_schema(fk_schema);
+  command.set_fk_table(fk_table);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.GetCrossReference(call_options, &pk_catalog, &pk_schema, pk_table,
+                                         &fk_catalog, &fk_schema, fk_table));
+}
+
+TEST_F(TestFlightSqlClient, TestExecute) {
+  std::string query = "query";
+
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+  FlightDescriptor descriptor = getDescriptor(command);
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+
+  ASSERT_OK(sql_client.Execute(call_options, query));
+}
+
+TEST_F(TestFlightSqlClient, TestPreparedStatementExecute) {
+  const std::string query = "query";
+
+  ON_CALL(sql_client, DoAction)
+      .WillByDefault([](const FlightCallOptions& options, const Action& action,
+                        std::unique_ptr<ResultStream>* results) {
+        google::protobuf::Any command;
+
+        pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+        prepared_statement_result.set_prepared_statement_handle("query");
+
+        command.PackFrom(prepared_statement_result);
+
+        *results = std::unique_ptr<ResultStream>(new SimpleResultStream(
+            {Result{Buffer::FromString(command.SerializeAsString())}}));
+
+        return Status::OK();
+      });
+
+  EXPECT_CALL(sql_client, DoAction(_, _, _)).Times(2);
+
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement, sql_client.Prepare(call_options, query));
+
+  EXPECT_CALL(sql_client, GetFlightInfo(_, _, _));
+
+  ASSERT_OK(prepared_statement->Execute());
+}
+
+TEST_F(TestFlightSqlClient, TestPreparedStatementExecuteParameterBinding) {
+  const std::string query = "query";
+
+  ON_CALL(sql_client, DoAction)
+      .WillByDefault([](const FlightCallOptions& options, const Action& action,
+                        std::unique_ptr<ResultStream>* results) {
+        google::protobuf::Any command;
+
+        pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+        prepared_statement_result.set_prepared_statement_handle("query");
+
+        auto schema = arrow::schema({arrow::field("id", int64())});
+
+        std::shared_ptr<Buffer> schema_buffer;
+        const arrow::Result<std::shared_ptr<Buffer>>& result =
+            arrow::ipc::SerializeSchema(*schema);
+
+        ARROW_ASSIGN_OR_RAISE(schema_buffer, result);
+
+        prepared_statement_result.set_parameter_schema(schema_buffer->ToString());
+
+        command.PackFrom(prepared_statement_result);
+
+        *results = std::unique_ptr<ResultStream>(new SimpleResultStream(
+            {Result{Buffer::FromString(command.SerializeAsString())}}));
+
+        return Status::OK();
+      });
+
+  std::shared_ptr<Buffer> buffer_ptr;
+  ON_CALL(sql_client, DoPut)
+      .WillByDefault([&buffer_ptr](const FlightCallOptions& options,
+                                   const FlightDescriptor& descriptor1,
+                                   const std::shared_ptr<Schema>& schema,
+                                   std::unique_ptr<FlightStreamWriter>* writer,
+                                   std::unique_ptr<FlightMetadataReader>* reader) {
+        writer->reset(new FlightStreamWriterMock());
+        reader->reset(new FlightMetadataReaderMock(&buffer_ptr));
+
+        return Status::OK();
+      });
+
+  EXPECT_CALL(sql_client, DoAction(_, _, _)).Times(2);
+  EXPECT_CALL(sql_client, DoPut(_, _, _, _, _));
+
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement, sql_client.Prepare(call_options, query));
+
+  auto parameter_schema = prepared_statement->parameter_schema();
+
+  arrow::Int64Builder int_builder;
+  ASSERT_OK(int_builder.Append(1));
+  std::shared_ptr<arrow::Array> int_array;
+  ASSERT_OK(int_builder.Finish(&int_array));
+  std::shared_ptr<arrow::RecordBatch> result;
+  result = arrow::RecordBatch::Make(parameter_schema, 1, {int_array});
+  ASSERT_OK(prepared_statement->SetParameters(result));
+
+  EXPECT_CALL(sql_client, GetFlightInfo(_, _, _));
+
+  ASSERT_OK(prepared_statement->Execute());
+}
+
+TEST_F(TestFlightSqlClient, TestExecuteUpdate) {
+  std::string query = "query";
+
+  pb::sql::CommandStatementUpdate command;
+
+  command.set_query(query);
+
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const FlightDescriptor& descriptor = FlightDescriptor::Command(any.SerializeAsString());
+
+  pb::sql::DoPutUpdateResult doPutUpdateResult;
+  doPutUpdateResult.set_record_count(100);
+  const std::string& string = doPutUpdateResult.SerializeAsString();
+
+  auto buffer_ptr = std::make_shared<Buffer>(
+      reinterpret_cast<const uint8_t*>(string.data()), doPutUpdateResult.ByteSizeLong());
+
+  ON_CALL(sql_client, DoPut)
+      .WillByDefault([&buffer_ptr](const FlightCallOptions& options,
+                                   const FlightDescriptor& descriptor1,
+                                   const std::shared_ptr<Schema>& schema,
+                                   std::unique_ptr<FlightStreamWriter>* writer,
+                                   std::unique_ptr<FlightMetadataReader>* reader) {
+        reader->reset(new FlightMetadataReaderMock(&buffer_ptr));
+
+        return Status::OK();
+      });
+
+  std::unique_ptr<FlightInfo> flight_info;
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+  EXPECT_CALL(sql_client, DoPut(Ref(call_options), descriptor, _, _, _));
+
+  ASSERT_OK_AND_ASSIGN(auto num_rows, sql_client.ExecuteUpdate(call_options, query));
+
+  ASSERT_EQ(num_rows, 100);
+}
+
+TEST_F(TestFlightSqlClient, TestGetSqlInfo) {
+  std::vector<int> sql_info{pb::sql::SqlInfo::FLIGHT_SQL_SERVER_NAME,
+                            pb::sql::SqlInfo::FLIGHT_SQL_SERVER_VERSION,
+                            pb::sql::SqlInfo::FLIGHT_SQL_SERVER_ARROW_VERSION};
+  pb::sql::CommandGetSqlInfo command;
+
+  for (const auto& info : sql_info) command.add_info(info);
+  google::protobuf::Any any;
+  any.PackFrom(command);
+  const FlightDescriptor& descriptor = FlightDescriptor::Command(any.SerializeAsString());
+
+  EXPECT_CALL(sql_client, GetFlightInfo(Ref(call_options), descriptor, _));
+  ASSERT_OK(sql_client.GetSqlInfo(call_options, sql_info));
+}
+
+template <class Func>
+inline void AssertTestPreparedStatementExecuteUpdateOk(
+    Func func, const std::shared_ptr<Schema>* schema, FlightSqlClientMock& sql_client) {
+  const std::string query = "SELECT * FROM IRRELEVANT";
+  int64_t expected_rows = 100L;
+  pb::sql::DoPutUpdateResult result;
+  result.set_record_count(expected_rows);
+
+  ON_CALL(sql_client, DoAction)
+      .WillByDefault([&query, &schema](const FlightCallOptions& options,
+                                       const Action& action,
+                                       std::unique_ptr<ResultStream>* results) {
+        google::protobuf::Any command;
+        pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+        prepared_statement_result.set_prepared_statement_handle(query);
+
+        if (schema != NULLPTR) {
+          std::shared_ptr<Buffer> schema_buffer;
+          const arrow::Result<std::shared_ptr<Buffer>>& result =
+              arrow::ipc::SerializeSchema(**schema);
+
+          ARROW_ASSIGN_OR_RAISE(schema_buffer, result);
+          prepared_statement_result.set_parameter_schema(schema_buffer->ToString());
+        }
+
+        command.PackFrom(prepared_statement_result);
+        *results = std::unique_ptr<ResultStream>(new SimpleResultStream(
+            {Result{Buffer::FromString(command.SerializeAsString())}}));
+
+        return Status::OK();
+      });
+  EXPECT_CALL(sql_client, DoAction(_, _, _)).Times(2);
+
+  auto buffer = Buffer::FromString(result.SerializeAsString());
+  ON_CALL(sql_client, DoPut)
+      .WillByDefault([&buffer](const FlightCallOptions& options,
+                               const FlightDescriptor& descriptor1,
+                               const std::shared_ptr<Schema>& schema,
+                               std::unique_ptr<FlightStreamWriter>* writer,
+                               std::unique_ptr<FlightMetadataReader>* reader) {
+        reader->reset(new FlightMetadataReaderMock(&buffer));
+        writer->reset(new FlightStreamWriterMock());
+        return Status::OK();
+      });
+  if (schema == NULLPTR) {
+    EXPECT_CALL(sql_client, DoPut(_, _, _, _, _));
+  } else {
+    EXPECT_CALL(sql_client, DoPut(_, _, *schema, _, _));
+  }
+
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement, sql_client.Prepare({}, query));
+  func(prepared_statement, sql_client, schema, expected_rows);
+  ASSERT_OK_AND_ASSIGN(auto rows, prepared_statement->ExecuteUpdate());
+  ASSERT_EQ(expected_rows, rows);

Review comment:
       Explicitly close the prepared statement here?

##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       I don't think we can require users to link to FlightSql.pb.cc separately and I've observed this crashing anyways despite the current workaround.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r736762091



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,107 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
+                                                  ${GFLAGS_LIBRARIES})
+
+add_arrow_test(flight_sql_test
+        SOURCES
+        client_test.cc
+        server_test.cc
+        "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+        STATIC_LINK_LIBS
+        ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+        LABELS
+        "arrow_flight_sql")
+
+# Build test server for unit tests
+if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
+  find_package(SQLite3)

Review comment:
       This depends on CMake 3.14+; also we should set `REQUIRED` to prevent errors later.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756367453



##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);

Review comment:
       Yes, it's because the filter is optional and the empty string has another meaning. This is decribed on FlightSql.proto




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-977944834


   "DbSchema" would indeed disambiguate slightly, especially at the API level.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jcralmeida commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jcralmeida commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746868379



##########
File path: cpp/src/arrow/flight/flight_sql/server.cc
##########
@@ -0,0 +1,663 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include <arrow/api.h>
+#include <arrow/buffer.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <google/protobuf/any.pb.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <sstream>
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+std::string FlightSqlServerBase::CreateStatementQueryTicket(

Review comment:
       This method is used in another classm so I can't remove from the header. I can transform it to a free function. Does it work?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746835960



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       Hmm, ok, I'll take another look too when I can.
   
   We might have to go with one of these options:
   - Only allow dynamically linking libarrow_flight_sql when Protobuf is also dynamically linked (hence under vcpkg we would have to statically link everything)
   - Remove libarrow_flight_sql and keep everything in libarrow_flight.so (however if one of the tests also needs to link Protobuf this won't fix things)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r748317982



##########
File path: cpp/src/arrow/flight/flight_sql/sql_info_util.h
##########
@@ -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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <boost/variant.hpp>

Review comment:
       There's a vendored variant type inside arrow/util/variant.h - can we use that instead?

##########
File path: cpp/src/arrow/flight/flight_sql/sql_info_util.h
##########
@@ -0,0 +1,84 @@
+// Licensed to the Apache Software Foundation (ASF) under one

Review comment:
       If this is an internal header, can we name it `sql_info_internal.h` so it doesn't get installed?

##########
File path: cpp/src/arrow/flight/flight_sql/sql_info_util.cc
##########
@@ -0,0 +1,113 @@
+// 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/api.h>
+#include <arrow/buffer.h>
+#include <arrow/flight/flight_sql/sql_info_util.h>
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+#define REGISTER_FIELD(name, type, nullable) \
+  const auto& name = field(ARROW_STRINGIFY(name), type, nullable);
+
+#define REGISTER_FIELD_NOT_NULL(name, type) REGISTER_FIELD(name, type, false)

Review comment:
       None of these macros seem used here.

##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_statement.cc
##########
@@ -0,0 +1,140 @@
+// 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/flight_sql/example/sqlite_statement.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+
+#include "arrow/flight/flight_sql/example/sqlite_server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetDataTypeFromSqliteType(const int column_type) {
+  switch (column_type) {
+    case SQLITE_INTEGER:
+      return int64();
+    case SQLITE_FLOAT:
+      return float64();
+    case SQLITE_BLOB:
+      return binary();
+    case SQLITE_TEXT:
+      return utf8();
+    case SQLITE_NULL:
+    default:
+      return null();
+  }
+}
+
+arrow::Result<std::shared_ptr<SqliteStatement>> SqliteStatement::Create(
+    sqlite3* db, const std::string& sql) {
+  sqlite3_stmt* stmt = nullptr;
+  int rc =
+      sqlite3_prepare_v2(db, sql.c_str(), static_cast<int>(sql.size()), &stmt, NULLPTR);
+
+  if (rc != SQLITE_OK) {
+    std::string err_msg = "Can't prepare statement: " + std::string(sqlite3_errmsg(db));
+    if (stmt != nullptr) {
+      rc = sqlite3_finalize(stmt);
+      if (rc != SQLITE_OK) {
+        err_msg += "; Failed to finalize SQLite statement: ";
+        err_msg += std::string(sqlite3_errmsg(db));
+      }
+    }
+    return Status::Invalid(err_msg);
+  }
+
+  std::shared_ptr<SqliteStatement> result(new SqliteStatement(db, stmt));
+  return result;
+}
+
+Status SqliteStatement::GetSchema(std::shared_ptr<Schema>* schema) const {
+  std::vector<std::shared_ptr<Field>> fields;
+  int column_count = sqlite3_column_count(stmt_);
+  for (int i = 0; i < column_count; i++) {
+    const char* column_name = sqlite3_column_name(stmt_, i);
+
+    // SQLite does not always provide column types, especially when the statement has not
+    // been executed yet. Because of this behaviour this method tries to get the column
+    // types in two attempts:
+    // 1. Use sqlite3_column_type(), which return SQLITE_NULL if the statement has not
+    //    been executed yet
+    // 2. Use sqlite3_column_decltype(), which returns correctly if given column is
+    //    declared in the table.
+    // Because of this limitation, it is not possible to know the column types for some
+    // prepared statements, in this case it returns a dense_union type covering any type
+    // SQLite supports.
+    const int column_type = sqlite3_column_type(stmt_, i);
+    std::shared_ptr<DataType> data_type = GetDataTypeFromSqliteType(column_type);
+    if (data_type->id() == Type::NA) {
+      // Try to retrieve column type from sqlite3_column_decltype
+      const char* column_decltype = sqlite3_column_decltype(stmt_, i);
+      if (column_decltype != NULLPTR) {
+        data_type = GetArrowType(column_decltype);
+      } else {
+        // If it can not determine the actual column type, return a dense_union type
+        // covering any type SQLite supports.
+        data_type = GetUnknownColumnDataType();
+      }
+    }
+
+    fields.push_back(arrow::field(column_name, data_type));
+  }
+
+  *schema = arrow::schema(fields);
+  return Status::OK();
+}
+
+SqliteStatement::~SqliteStatement() { sqlite3_finalize(stmt_); }
+
+Status SqliteStatement::Step(int* rc) {
+  *rc = sqlite3_step(stmt_);
+  if (*rc == SQLITE_ERROR) {
+    return Status::RError("A SQLite runtime error has occurred: ", sqlite3_errmsg(db_));

Review comment:
       RError is for R.

##########
File path: cpp/src/arrow/flight/flight_sql/server.cc
##########
@@ -0,0 +1,772 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/flight_sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/flight_sql/FlightSql.pb.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+#define REGISTER_FIELD(name, type, nullable) \
+  const auto& name = field(ARROW_STRINGIFY(name), type, nullable);
+
+#define REGISTER_FIELD_NOT_NULL(name, type) REGISTER_FIELD(name, type, false)
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any,
+    const sql_info_id_to_result_t& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::ListActions(const ServerCallContext& context,
+                                        std::vector<ActionType>* actions) {
+  *actions = {FlightSqlServerBase::kCreatePreparedStatementActionType,
+              FlightSqlServerBase::kClosePreparedStatementActionType};
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::DoAction(const ServerCallContext& context,
+                                     const Action& action,
+                                     std::unique_ptr<ResultStream>* result_stream) {
+  if (action.type == FlightSqlServerBase::kCreatePreparedStatementActionType.type) {
+    google::protobuf::Any any_command;
+    if (!any_command.ParseFromArray(action.body->data(),
+                                    static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionCreatePreparedStatementRequest internal_command,
+                          ParseActionCreatePreparedStatementRequest(any_command));
+    ARROW_ASSIGN_OR_RAISE(auto result, CreatePreparedStatement(context, internal_command))
+
+    pb::sql::ActionCreatePreparedStatementResult action_result;
+    action_result.set_prepared_statement_handle(result.prepared_statement_handle);
+    if (result.dataset_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_dataset_schema,
+                            ipc::SerializeSchema(*result.dataset_schema))
+      action_result.set_dataset_schema(serialized_dataset_schema->ToString());
+    }
+    if (result.parameter_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_parameter_schema,
+                            ipc::SerializeSchema(*result.parameter_schema))
+      action_result.set_parameter_schema(serialized_parameter_schema->ToString());
+    }
+
+    google::protobuf::Any any;
+    any.PackFrom(action_result);
+
+    auto buf = Buffer::FromString(any.SerializeAsString());
+    *result_stream = std::unique_ptr<ResultStream>(new SimpleResultStream({Result{buf}}));
+
+    return Status::OK();
+  } else if (action.type == FlightSqlServerBase::kClosePreparedStatementActionType.type) {
+    google::protobuf::Any any;
+    if (!any.ParseFromArray(action.body->data(), static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionClosePreparedStatementRequest internal_command,
+                          ParseActionClosePreparedStatementRequest(any));
+
+    return ClosePreparedStatement(context, internal_command, result_stream);
+  }
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCatalogs(const ServerCallContext& context,
+                                                  const FlightDescriptor& descriptor,
+                                                  std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCatalogs(const ServerCallContext& context,
+                                          std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoStatement(const ServerCallContext& context,
+                                                   const StatementQuery& command,
+                                                   const FlightDescriptor& descriptor,
+                                                   std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetStatement(const ServerCallContext& context,
+                                           const StatementQueryTicket& command,
+                                           std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                                 const GetSqlInfo& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  assert(info != nullptr);
+
+  if (sql_info_id_to_result_.empty()) {
+    return Status::NotImplemented("GetFlightInfoSqlInfo not implemented");
+  }
+
+  std::vector<FlightEndpoint> endpoints{FlightEndpoint{{descriptor.cmd}, {}}};
+  ARROW_ASSIGN_OR_RAISE(auto result, FlightInfo::Make(*SqlSchema::GetSqlInfoSchema(),
+                                                      descriptor, endpoints, -1, -1))
+
+  *info = std::unique_ptr<FlightInfo>(new FlightInfo(result));
+
+  return Status::OK();
+}
+
+void FlightSqlServerBase::RegisterSqlInfo(int32_t id, const SqlInfoResult& result) {
+  sql_info_id_to_result_[id] = result;
+}
+
+Status FlightSqlServerBase::DoGetSqlInfo(const ServerCallContext& context,
+                                         const GetSqlInfo& command,
+                                         std::unique_ptr<FlightDataStream>* result) {
+  assert(result != nullptr);
+
+  MemoryPool* memory_pool = default_memory_pool();
+  UInt32Builder name_field_builder(memory_pool);
+  const std::shared_ptr<StringBuilder> string_value_field_builder(
+      new StringBuilder(memory_pool));
+  const std::shared_ptr<BooleanBuilder> bool_value_field_builder(
+      new BooleanBuilder(memory_pool));
+  const std::shared_ptr<Int64Builder> bigint_value_field_builder(
+      new Int64Builder(memory_pool));
+  const std::shared_ptr<Int32Builder> int32_bitmask_field_builder(
+      new Int32Builder(memory_pool));
+  const std::shared_ptr<StringBuilder> string_list_inner_string_field_builder(
+      new StringBuilder(memory_pool));
+  const std::shared_ptr<ListBuilder> string_list_field_builder(
+      new ListBuilder(memory_pool, string_list_inner_string_field_builder));
+  const std::shared_ptr<Int32Builder> int32_to_int32_list_key_builder(
+      new Int32Builder(memory_pool));
+  const std::shared_ptr<Int32Builder> int32_to_int32_list_elements_in_value_list(
+      new Int32Builder(memory_pool));
+  const std::shared_ptr<ListBuilder> int32_to_int32_list_value_builder(
+      new ListBuilder(memory_pool, int32_to_int32_list_elements_in_value_list));
+  const std::shared_ptr<MapBuilder> int32_to_int32_list_map_field_builder(new MapBuilder(
+      memory_pool, int32_to_int32_list_key_builder, int32_to_int32_list_value_builder));
+  std::vector<std::shared_ptr<ArrayBuilder>> value_field_builders{
+      string_value_field_builder, bool_value_field_builder,
+      bigint_value_field_builder, int32_bitmask_field_builder,
+      string_list_field_builder,  int32_to_int32_list_map_field_builder};
+  const std::shared_ptr<Schema>& schema = SqlSchema::GetSqlInfoSchema();
+  const auto& union_type = schema->fields()[1]->type();  // expected union type.
+  DenseUnionBuilder value_field_builder(memory_pool, value_field_builders, union_type);
+  internal::SqlInfoResultAppender sql_info_result_appender(value_field_builder);
+
+  // Populate both name_field_builder and value_field_builder for each element
+  // on command.info.
+  // value_field_builder is populated differently depending on the data type (as it is
+  // a DenseUnionBuilder). The population for each data type is implemented on
+  // internal::SqlInfoResultAppender.
+  for (const auto& info : command.info) {
+    if (!sql_info_id_to_result_.count(info)) {
+      return Status::KeyError(
+          "Attempt to fetch unregistered/unsupported SqlInfo option: " +
+          std::to_string(info));
+    }
+    ARROW_RETURN_NOT_OK(name_field_builder.Append(info));
+    ARROW_RETURN_NOT_OK(
+        boost::apply_visitor(sql_info_result_appender, sql_info_id_to_result_.at(info)));
+  }
+
+  std::shared_ptr<Array> name;
+  ARROW_RETURN_NOT_OK(name_field_builder.Finish(&name));
+  std::shared_ptr<Array> value;
+  ARROW_RETURN_NOT_OK(value_field_builder.Finish(&value));
+
+  auto row_count = static_cast<int64_t>(command.info.size());
+  const std::shared_ptr<RecordBatch>& batch =
+      RecordBatch::Make(schema, row_count, {name, value});
+  ARROW_ASSIGN_OR_RAISE(const auto reader, RecordBatchReader::Make({batch}));
+  *result = std::unique_ptr<FlightDataStream>(new RecordBatchStream(reader));
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::GetFlightInfoSchemas(const ServerCallContext& context,
+                                                 const GetSchemas& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoSchemas not implemented");
+}
+
+Status FlightSqlServerBase::DoGetSchemas(const ServerCallContext& context,
+                                         const GetSchemas& command,
+                                         std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetSchemas not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoTables(const ServerCallContext& context,
+                                                const GetTables& command,
+                                                const FlightDescriptor& descriptor,
+                                                std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoTables not implemented");
+}
+
+Status FlightSqlServerBase::DoGetTables(const ServerCallContext& context,
+                                        const GetTables& command,
+                                        std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetTables not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoTableTypes(const ServerCallContext& context,
+                                                    const FlightDescriptor& descriptor,
+                                                    std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoTableTypes not implemented");
+}
+
+Status FlightSqlServerBase::DoGetTableTypes(const ServerCallContext& context,
+                                            std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetTableTypes not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPrimaryKeys(const ServerCallContext& context,
+                                                     const GetPrimaryKeys& command,
+                                                     const FlightDescriptor& descriptor,
+                                                     std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPrimaryKeys not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPrimaryKeys(const ServerCallContext& context,
+                                             const GetPrimaryKeys& command,
+                                             std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPrimaryKeys not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoExportedKeys(const ServerCallContext& context,
+                                                      const GetExportedKeys& command,
+                                                      const FlightDescriptor& descriptor,
+                                                      std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoExportedKeys not implemented");
+}
+
+Status FlightSqlServerBase::DoGetExportedKeys(const ServerCallContext& context,
+                                              const GetExportedKeys& command,
+                                              std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetExportedKeys not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoImportedKeys(const ServerCallContext& context,
+                                                      const GetImportedKeys& command,
+                                                      const FlightDescriptor& descriptor,
+                                                      std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoImportedKeys not implemented");
+}
+
+Status FlightSqlServerBase::DoGetImportedKeys(const ServerCallContext& context,
+                                              const GetImportedKeys& command,
+                                              std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetImportedKeys not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCrossReference(
+    const ServerCallContext& context, const GetCrossReference& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCrossReference not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCrossReference(
+    const ServerCallContext& context, const GetCrossReference& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCrossReference not implemented");
+}
+
+arrow::Result<ActionCreatePreparedStatementResult>
+FlightSqlServerBase::CreatePreparedStatement(
+    const ServerCallContext& context,
+    const ActionCreatePreparedStatementRequest& request) {
+  return Status::NotImplemented("CreatePreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::ClosePreparedStatement(
+    const ServerCallContext& context, const ActionClosePreparedStatementRequest& request,
+    std::unique_ptr<ResultStream>* result) {
+  return Status::NotImplemented("ClosePreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoPutPreparedStatementQuery(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    FlightMessageReader* reader, FlightMetadataWriter* writer) {
+  return Status::NotImplemented("DoPutPreparedStatementQuery not implemented");
+}
+
+arrow::Result<int64_t> FlightSqlServerBase::DoPutPreparedStatementUpdate(
+    const ServerCallContext& context, const PreparedStatementUpdate& command,
+    FlightMessageReader* reader) {
+  return Status::NotImplemented("DoPutPreparedStatementUpdate not implemented");
+}
+
+arrow::Result<int64_t> FlightSqlServerBase::DoPutCommandStatementUpdate(
+    const ServerCallContext& context, const StatementUpdate& command,
+    std::unique_ptr<FlightMessageReader>& reader) {
+  return Status::NotImplemented("DoPutCommandStatementUpdate not implemented");
+}
+
+std::shared_ptr<Schema> SqlSchema::GetCatalogsSchema() {
+  return arrow::schema({field("catalog_name", utf8())});
+}
+
+std::shared_ptr<Schema> SqlSchema::GetSchemasSchema() {
+  return arrow::schema(
+      {field("catalog_name", utf8()), field("schema_name", utf8(), false)});
+}
+
+std::shared_ptr<Schema> SqlSchema::GetTablesSchema() {
+  return arrow::schema({field("catalog_name", utf8()), field("schema_name", utf8()),
+                        field("table_name", utf8()), field("table_type", utf8())});
+}
+
+std::shared_ptr<Schema> SqlSchema::GetTablesSchemaWithIncludedSchema() {
+  return arrow::schema({field("catalog_name", utf8()), field("schema_name", utf8()),
+                        field("table_name", utf8()), field("table_type", utf8()),
+                        field("table_schema", binary())});
+}
+
+std::shared_ptr<Schema> SqlSchema::GetTableTypesSchema() {
+  return arrow::schema({field("table_type", utf8())});
+}
+
+std::shared_ptr<Schema> SqlSchema::GetPrimaryKeysSchema() {
+  return arrow::schema({field("catalog_name", utf8()), field("schema_name", utf8()),
+                        field("table_name", utf8()), field("column_name", utf8()),
+                        field("key_sequence", int64()), field("key_name", utf8())});
+}
+
+std::shared_ptr<Schema> GetImportedExportedKeysAndCrossReferenceSchema() {
+  return arrow::schema(
+      {field("pk_catalog_name", utf8(), true), field("pk_schema_name", utf8(), true),
+       field("pk_table_name", utf8(), false), field("pk_column_name", utf8(), false),
+       field("fk_catalog_name", utf8(), true), field("fk_schema_name", utf8(), true),
+       field("fk_table_name", utf8(), false), field("fk_column_name", utf8(), false),
+       field("key_sequence", int32(), false), field("fk_key_name", utf8(), true),
+       field("pk_key_name", utf8(), true), field("update_rule", uint8(), false),
+       field("delete_rule", uint8(), false)});
+}
+
+std::shared_ptr<Schema> SqlSchema::GetImportedKeysSchema() {
+  return GetImportedExportedKeysAndCrossReferenceSchema();
+}
+
+std::shared_ptr<Schema> SqlSchema::GetExportedKeysSchema() {
+  return GetImportedExportedKeysAndCrossReferenceSchema();
+}
+
+std::shared_ptr<Schema> SqlSchema::GetCrossReferenceSchema() {
+  return GetImportedExportedKeysAndCrossReferenceSchema();
+}
+
+std::shared_ptr<Schema> SqlSchema::GetSqlInfoSchema() {
+  REGISTER_FIELD_NOT_NULL(name, uint32())
+  REGISTER_FIELD_NOT_NULL(string_value, utf8())
+  REGISTER_FIELD_NOT_NULL(bool_value, boolean())
+  REGISTER_FIELD_NOT_NULL(bigint_value, int64())
+  REGISTER_FIELD_NOT_NULL(int32_bitmask, int32())
+  REGISTER_FIELD_NOT_NULL(string_list, list(utf8()))
+  REGISTER_FIELD_NOT_NULL(int32_to_int32_list_map, map(int32(), list(int32())))
+  const FieldVector value_fields{string_value,  bool_value,  bigint_value,
+                                 int32_bitmask, string_list, int32_to_int32_list_map};
+  REGISTER_FIELD_NOT_NULL(value, dense_union(value_fields))
+  return arrow::schema({name, value});

Review comment:
       Ok, are the macros really useful here? They just make it unclear what's going on. Why not something like 
   
   ```cpp
   auto name = field("name", uint32(), /*nullable=*/false);
   auto value = dense_union({
       field("string_value", utf8(), /*nullable=*/false),
       ...
   });
   return arrow::schema({name, value});
   ```

##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_statement.cc
##########
@@ -0,0 +1,140 @@
+// 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/flight_sql/example/sqlite_statement.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+
+#include "arrow/flight/flight_sql/example/sqlite_server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetDataTypeFromSqliteType(const int column_type) {
+  switch (column_type) {
+    case SQLITE_INTEGER:
+      return int64();
+    case SQLITE_FLOAT:
+      return float64();
+    case SQLITE_BLOB:
+      return binary();
+    case SQLITE_TEXT:
+      return utf8();
+    case SQLITE_NULL:
+    default:
+      return null();
+  }
+}
+
+arrow::Result<std::shared_ptr<SqliteStatement>> SqliteStatement::Create(
+    sqlite3* db, const std::string& sql) {
+  sqlite3_stmt* stmt = nullptr;
+  int rc =
+      sqlite3_prepare_v2(db, sql.c_str(), static_cast<int>(sql.size()), &stmt, NULLPTR);
+
+  if (rc != SQLITE_OK) {
+    std::string err_msg = "Can't prepare statement: " + std::string(sqlite3_errmsg(db));
+    if (stmt != nullptr) {
+      rc = sqlite3_finalize(stmt);
+      if (rc != SQLITE_OK) {
+        err_msg += "; Failed to finalize SQLite statement: ";
+        err_msg += std::string(sqlite3_errmsg(db));
+      }
+    }
+    return Status::Invalid(err_msg);
+  }
+
+  std::shared_ptr<SqliteStatement> result(new SqliteStatement(db, stmt));
+  return result;
+}
+
+Status SqliteStatement::GetSchema(std::shared_ptr<Schema>* schema) const {
+  std::vector<std::shared_ptr<Field>> fields;
+  int column_count = sqlite3_column_count(stmt_);
+  for (int i = 0; i < column_count; i++) {
+    const char* column_name = sqlite3_column_name(stmt_, i);
+
+    // SQLite does not always provide column types, especially when the statement has not
+    // been executed yet. Because of this behaviour this method tries to get the column
+    // types in two attempts:
+    // 1. Use sqlite3_column_type(), which return SQLITE_NULL if the statement has not
+    //    been executed yet
+    // 2. Use sqlite3_column_decltype(), which returns correctly if given column is
+    //    declared in the table.
+    // Because of this limitation, it is not possible to know the column types for some
+    // prepared statements, in this case it returns a dense_union type covering any type
+    // SQLite supports.
+    const int column_type = sqlite3_column_type(stmt_, i);
+    std::shared_ptr<DataType> data_type = GetDataTypeFromSqliteType(column_type);
+    if (data_type->id() == Type::NA) {
+      // Try to retrieve column type from sqlite3_column_decltype
+      const char* column_decltype = sqlite3_column_decltype(stmt_, i);
+      if (column_decltype != NULLPTR) {
+        data_type = GetArrowType(column_decltype);
+      } else {
+        // If it can not determine the actual column type, return a dense_union type
+        // covering any type SQLite supports.
+        data_type = GetUnknownColumnDataType();
+      }
+    }
+
+    fields.push_back(arrow::field(column_name, data_type));
+  }
+
+  *schema = arrow::schema(fields);
+  return Status::OK();
+}
+
+SqliteStatement::~SqliteStatement() { sqlite3_finalize(stmt_); }
+
+Status SqliteStatement::Step(int* rc) {
+  *rc = sqlite3_step(stmt_);
+  if (*rc == SQLITE_ERROR) {
+    return Status::RError("A SQLite runtime error has occurred: ", sqlite3_errmsg(db_));

Review comment:
       There's 3 uses still:
   
   ```
   cpp/src/arrow/flight/flight_sql/example/sqlite_server.cc
   223:    return Status::RError(error_msg);
   
   cpp/src/arrow/flight/flight_sql/example/sqlite_statement.cc
   111:    return Status::RError("A SQLite runtime error has occurred: ", sqlite3_errmsg(db_));
   120:    return Status::RError("A SQLite runtime error has occurred: ", sqlite3_errmsg(db_));
   ```

##########
File path: cpp/src/arrow/flight/flight_sql/sql_info_util.h
##########
@@ -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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <boost/variant.hpp>
+
+using string_list_t = std::vector<std::string>;
+using int32_to_int32_list_t = std::unordered_map<int32_t, std::vector<int32_t>>;
+using SqlInfoResult = boost::variant<std::string, bool, int64_t, int32_t, string_list_t,
+                                     int32_to_int32_list_t>;
+using sql_info_id_to_result_t = std::unordered_map<int32_t, SqlInfoResult>;

Review comment:
       I don't think Arrow uses the stdlib `_t` naming convention for typedefs, and I'm not sure `string_list_t` saves much (or is any clearer than) `std::vector<std::string>`. Perhaps these could be something like `SqlInfoEnumVectorMap` and `SqlInfoResultMap`.

##########
File path: cpp/src/arrow/flight/flight_sql/server.h
##########
@@ -0,0 +1,504 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <boost/variant.hpp>
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/flight_sql/example/sqlite_statement.h"
+#include "arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight_sql/server.h"
+#include "arrow/flight/flight_sql/sql_info_util.h"

Review comment:
       Ditto the comments below - we can define the variant type in a common header (or even just here), and keep the utilities in an internal header.

##########
File path: cpp/src/arrow/flight/flight_sql/server.h
##########
@@ -0,0 +1,504 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <boost/variant.hpp>
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/flight_sql/example/sqlite_statement.h"
+#include "arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h"

Review comment:
       Why is SQLite in the common server header?

##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,177 @@
+// 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/flight_sql/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/api.h"

Review comment:
       Note that including `arrow/api.h` is relatively heavy and it's probably better to break down the includes you need (e.g. `arrow/builder.h`)

##########
File path: cpp/src/arrow/flight/flight_sql/server.h
##########
@@ -0,0 +1,504 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <boost/variant.hpp>
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/flight_sql/example/sqlite_statement.h"
+#include "arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight_sql/server.h"
+#include "arrow/flight/flight_sql/sql_info_util.h"
+#include "arrow/flight/server.h"
+#include "arrow/util/optional.h"
+
+using string_list_t = std::vector<std::string>;
+using int32_to_int32_list_t = std::unordered_map<int32_t, std::vector<int32_t>>;
+using SqlInfoResult = boost::variant<std::string, bool, int64_t, int32_t, string_list_t,
+                                     int32_to_int32_list_t>;
+using sql_info_id_to_result_t = std::unordered_map<int32_t, SqlInfoResult>;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  std::vector<int32_t> info;
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;
+  util::optional<std::string> fk_catalog;
+  util::optional<std::string> fk_schema;
+  std::string fk_table;
+};
+
+struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+/// \brief A free function responsible to create a ticket for the statement operation.
+///        It is used by the server implementation.

Review comment:
       ```suggestion
   /// \brief A utility function to create a ticket for a statement query.
   ///        Intended for Flight SQL server implementations.
   ```

##########
File path: cpp/src/arrow/flight/flight_sql/sql_info_util.cc
##########
@@ -0,0 +1,113 @@
+// 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/api.h>
+#include <arrow/buffer.h>
+#include <arrow/flight/flight_sql/sql_info_util.h>

Review comment:
       note: we usually include Arrow headers with quotes instead of brackets

##########
File path: cpp/src/arrow/flight/flight_sql/sql_info_util.cc
##########
@@ -0,0 +1,113 @@
+// 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/api.h>
+#include <arrow/buffer.h>
+#include <arrow/flight/flight_sql/sql_info_util.h>
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+#define REGISTER_FIELD(name, type, nullable) \
+  const auto& name = field(ARROW_STRINGIFY(name), type, nullable);
+
+#define REGISTER_FIELD_NOT_NULL(name, type) REGISTER_FIELD(name, type, false)
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+Status SqlInfoResultAppender::operator()(const std::string& value) {
+  const int8_t type_index = STRING_VALUE_INDEX;
+  ARROW_RETURN_NOT_OK(value_builder_.Append(type_index));
+  auto* string_value_builder =
+      reinterpret_cast<StringBuilder*>(value_builder_.child(type_index));
+  ARROW_RETURN_NOT_OK(string_value_builder->Append(value));
+  return Status::OK();
+}
+
+Status SqlInfoResultAppender::operator()(const bool value) {
+  const int8_t type_index = BOOL_VALUE_INDEX;
+  ARROW_RETURN_NOT_OK(value_builder_.Append(type_index));
+  auto* bool_value_builder =
+      reinterpret_cast<BooleanBuilder*>(value_builder_.child(type_index));
+  ARROW_RETURN_NOT_OK(bool_value_builder->Append(value));
+  return Status::OK();
+}
+
+Status SqlInfoResultAppender::operator()(const int64_t value) {
+  const int8_t type_index = BIGINT_VALUE_INDEX;
+  ARROW_RETURN_NOT_OK(value_builder_.Append(type_index));
+  auto* bigint_value_builder =
+      reinterpret_cast<Int64Builder*>(value_builder_.child(type_index));
+  ARROW_RETURN_NOT_OK(bigint_value_builder->Append(value));
+  return Status::OK();
+}
+
+Status SqlInfoResultAppender::operator()(const int32_t value) {
+  const int8_t type_index = INT32_BITMASK_INDEX;
+  ARROW_RETURN_NOT_OK(value_builder_.Append(type_index));
+  auto* int32_bitmask_builder =
+      reinterpret_cast<Int32Builder*>(value_builder_.child(type_index));
+  ARROW_RETURN_NOT_OK(int32_bitmask_builder->Append(value));
+  return Status::OK();
+}
+
+Status SqlInfoResultAppender::operator()(const string_list_t& value) {
+  const int8_t type_index = STRING_LIST_INDEX;
+  ARROW_RETURN_NOT_OK(value_builder_.Append(type_index));
+  auto* string_list_builder =
+      reinterpret_cast<ListBuilder*>(value_builder_.child(type_index));
+  ARROW_RETURN_NOT_OK(string_list_builder->Append());
+  auto* string_list_child =
+      reinterpret_cast<StringBuilder*>(string_list_builder->value_builder());
+  for (const auto& string : value) {
+    ARROW_RETURN_NOT_OK(string_list_child->Append(string));
+  }
+  return Status::OK();
+}
+
+Status SqlInfoResultAppender::operator()(const int32_to_int32_list_t& value) {
+  const int8_t type_index = INT32_TO_INT32_LIST_INDEX;
+  ARROW_RETURN_NOT_OK(value_builder_.Append(type_index));
+  auto* int32_to_int32_list_builder =
+      reinterpret_cast<MapBuilder*>(value_builder_.child(type_index));
+  ARROW_RETURN_NOT_OK(int32_to_int32_list_builder->Append());
+  for (const auto& pair : value) {
+    ARROW_RETURN_NOT_OK(
+        reinterpret_cast<Int32Builder*>(int32_to_int32_list_builder->key_builder())
+            ->Append(pair.first));
+    auto* int32_list_builder =
+        reinterpret_cast<ListBuilder*>(int32_to_int32_list_builder->item_builder());
+    ARROW_RETURN_NOT_OK(int32_list_builder->Append());
+    auto* int32_list_child =
+        reinterpret_cast<Int32Builder*>(int32_list_builder->value_builder());
+    for (const auto& int32 : pair.second) {
+      ARROW_RETURN_NOT_OK(int32_list_child->Append(int32));
+    }
+  }
+  return Status::OK();
+}
+
+SqlInfoResultAppender::SqlInfoResultAppender(DenseUnionBuilder& value_builder)
+    : value_builder_(value_builder) {}

Review comment:
       If you wanted to avoid all the casts, you could prepopulate pointers to each of the child builders in the constructor.

##########
File path: cpp/src/arrow/flight/flight_sql/server.cc
##########
@@ -0,0 +1,772 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/flight_sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/flight_sql/FlightSql.pb.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+#define REGISTER_FIELD(name, type, nullable) \
+  const auto& name = field(ARROW_STRINGIFY(name), type, nullable);
+
+#define REGISTER_FIELD_NOT_NULL(name, type) REGISTER_FIELD(name, type, false)
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any,
+    const sql_info_id_to_result_t& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::ListActions(const ServerCallContext& context,
+                                        std::vector<ActionType>* actions) {
+  *actions = {FlightSqlServerBase::kCreatePreparedStatementActionType,
+              FlightSqlServerBase::kClosePreparedStatementActionType};
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::DoAction(const ServerCallContext& context,
+                                     const Action& action,
+                                     std::unique_ptr<ResultStream>* result_stream) {
+  if (action.type == FlightSqlServerBase::kCreatePreparedStatementActionType.type) {
+    google::protobuf::Any any_command;
+    if (!any_command.ParseFromArray(action.body->data(),
+                                    static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionCreatePreparedStatementRequest internal_command,
+                          ParseActionCreatePreparedStatementRequest(any_command));
+    ARROW_ASSIGN_OR_RAISE(auto result, CreatePreparedStatement(context, internal_command))
+
+    pb::sql::ActionCreatePreparedStatementResult action_result;
+    action_result.set_prepared_statement_handle(result.prepared_statement_handle);
+    if (result.dataset_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_dataset_schema,
+                            ipc::SerializeSchema(*result.dataset_schema))
+      action_result.set_dataset_schema(serialized_dataset_schema->ToString());
+    }
+    if (result.parameter_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_parameter_schema,
+                            ipc::SerializeSchema(*result.parameter_schema))
+      action_result.set_parameter_schema(serialized_parameter_schema->ToString());
+    }
+
+    google::protobuf::Any any;
+    any.PackFrom(action_result);
+
+    auto buf = Buffer::FromString(any.SerializeAsString());
+    *result_stream = std::unique_ptr<ResultStream>(new SimpleResultStream({Result{buf}}));
+
+    return Status::OK();
+  } else if (action.type == FlightSqlServerBase::kClosePreparedStatementActionType.type) {
+    google::protobuf::Any any;
+    if (!any.ParseFromArray(action.body->data(), static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionClosePreparedStatementRequest internal_command,
+                          ParseActionClosePreparedStatementRequest(any));
+
+    return ClosePreparedStatement(context, internal_command, result_stream);
+  }
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCatalogs(const ServerCallContext& context,
+                                                  const FlightDescriptor& descriptor,
+                                                  std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCatalogs(const ServerCallContext& context,
+                                          std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoStatement(const ServerCallContext& context,
+                                                   const StatementQuery& command,
+                                                   const FlightDescriptor& descriptor,
+                                                   std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetStatement(const ServerCallContext& context,
+                                           const StatementQueryTicket& command,
+                                           std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                                 const GetSqlInfo& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  assert(info != nullptr);
+
+  if (sql_info_id_to_result_.empty()) {
+    return Status::NotImplemented("GetFlightInfoSqlInfo not implemented");
+  }
+
+  std::vector<FlightEndpoint> endpoints{FlightEndpoint{{descriptor.cmd}, {}}};
+  ARROW_ASSIGN_OR_RAISE(auto result, FlightInfo::Make(*SqlSchema::GetSqlInfoSchema(),
+                                                      descriptor, endpoints, -1, -1))
+
+  *info = std::unique_ptr<FlightInfo>(new FlightInfo(result));
+
+  return Status::OK();
+}
+
+void FlightSqlServerBase::RegisterSqlInfo(int32_t id, const SqlInfoResult& result) {
+  sql_info_id_to_result_[id] = result;
+}
+
+Status FlightSqlServerBase::DoGetSqlInfo(const ServerCallContext& context,
+                                         const GetSqlInfo& command,
+                                         std::unique_ptr<FlightDataStream>* result) {
+  assert(result != nullptr);
+
+  MemoryPool* memory_pool = default_memory_pool();
+  UInt32Builder name_field_builder(memory_pool);
+  const std::shared_ptr<StringBuilder> string_value_field_builder(
+      new StringBuilder(memory_pool));
+  const std::shared_ptr<BooleanBuilder> bool_value_field_builder(
+      new BooleanBuilder(memory_pool));
+  const std::shared_ptr<Int64Builder> bigint_value_field_builder(
+      new Int64Builder(memory_pool));
+  const std::shared_ptr<Int32Builder> int32_bitmask_field_builder(
+      new Int32Builder(memory_pool));
+  const std::shared_ptr<StringBuilder> string_list_inner_string_field_builder(
+      new StringBuilder(memory_pool));
+  const std::shared_ptr<ListBuilder> string_list_field_builder(
+      new ListBuilder(memory_pool, string_list_inner_string_field_builder));
+  const std::shared_ptr<Int32Builder> int32_to_int32_list_key_builder(
+      new Int32Builder(memory_pool));
+  const std::shared_ptr<Int32Builder> int32_to_int32_list_elements_in_value_list(
+      new Int32Builder(memory_pool));
+  const std::shared_ptr<ListBuilder> int32_to_int32_list_value_builder(
+      new ListBuilder(memory_pool, int32_to_int32_list_elements_in_value_list));
+  const std::shared_ptr<MapBuilder> int32_to_int32_list_map_field_builder(new MapBuilder(
+      memory_pool, int32_to_int32_list_key_builder, int32_to_int32_list_value_builder));
+  std::vector<std::shared_ptr<ArrayBuilder>> value_field_builders{
+      string_value_field_builder, bool_value_field_builder,
+      bigint_value_field_builder, int32_bitmask_field_builder,
+      string_list_field_builder,  int32_to_int32_list_map_field_builder};
+  const std::shared_ptr<Schema>& schema = SqlSchema::GetSqlInfoSchema();
+  const auto& union_type = schema->fields()[1]->type();  // expected union type.
+  DenseUnionBuilder value_field_builder(memory_pool, value_field_builders, union_type);

Review comment:
       Note once you have the type, you can call `MakeBuilder` and it will create all the child builders for you. You can then cast it to the expected type.

##########
File path: cpp/src/arrow/flight/flight_sql/sql_info_util.h
##########
@@ -0,0 +1,84 @@
+// Licensed to the Apache Software Foundation (ASF) under one

Review comment:
       Especially since the typedefs are duplicated.

##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_server.h
##########
@@ -0,0 +1,351 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight_sql/FlightSql.pb.h"
+#include "arrow/flight/flight_sql/example/sqlite_statement.h"
+#include "arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight_sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+namespace flight_sql_pb = arrow::flight::protocol::sql;
+
+/// \brief Gets the mapping from SQL info ids to SqlInfoResult instances.
+/// \return the cache.
+inline sql_info_id_to_result_t GetSqlInfoIdToResult() {

Review comment:
       Why not move the body to the .cc file?

##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,258 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, const std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  /// \brief Retrieve the flightInfo. It is public because it is been used by the
+  /// anonymous function GetFlightInfoForCommand.

Review comment:
       ```suggestion
     /// \brief Retrieve a FlightInfo.
   ```

##########
File path: cpp/src/arrow/flight/flight_sql/server.cc
##########
@@ -0,0 +1,772 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/flight_sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/flight_sql/FlightSql.pb.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+#define REGISTER_FIELD(name, type, nullable) \
+  const auto& name = field(ARROW_STRINGIFY(name), type, nullable);
+
+#define REGISTER_FIELD_NOT_NULL(name, type) REGISTER_FIELD(name, type, false)
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle) {
+  protocol::sql::TicketStatementQuery ticket_statement_query;
+  ticket_statement_query.set_statement_handle(statement_handle);
+
+  google::protobuf::Any ticket;
+  ticket.PackFrom(ticket_statement_query);
+
+  std::string ticket_string;
+
+  if (!ticket.SerializeToString(&ticket_string)) {
+    return Status::IOError("Invalid ticket.");
+  }
+  return ticket_string;
+}
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(
+    const google::protobuf::Any& any,
+    const sql_info_id_to_result_t& sql_info_id_to_result) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  if (command.info_size() > 0) {
+    result.info.reserve(command.info_size());
+    result.info.assign(command.info().begin(), command.info().end());
+  } else {
+    result.info.reserve(sql_info_id_to_result.size());
+    for (const auto& it : sql_info_id_to_result) {
+      result.info.push_back(it.first);
+    }
+  }
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+Status FlightSqlServerBase::GetFlightInfo(const ServerCallContext& context,
+                                          const FlightDescriptor& request,
+                                          std::unique_ptr<FlightInfo>* info) {
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command");
+  }
+
+  if (any.Is<pb::sql::CommandStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQuery internal_command,
+                          ParseCommandStatementQuery(any));
+    return GetFlightInfoStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return GetFlightInfoPreparedStatement(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return GetFlightInfoCatalogs(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return GetFlightInfoSchemas(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return GetFlightInfoTables(context, command, request, info);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return GetFlightInfoTableTypes(context, request, info);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return GetFlightInfoSqlInfo(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return GetFlightInfoPrimaryKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return GetFlightInfoExportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return GetFlightInfoImportedKeys(context, internal_command, request, info);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return GetFlightInfoCrossReference(context, internal_command, request, info);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoGet(const ServerCallContext& context, const Ticket& request,
+                                  std::unique_ptr<FlightDataStream>* stream) {
+  google::protobuf::Any any;
+
+  if (!any.ParseFromArray(request.ticket.data(),
+                          static_cast<int>(request.ticket.size()))) {
+    return Status::Invalid("Unable to parse ticket.");
+  }
+
+  if (any.Is<pb::sql::TicketStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementQueryTicket command, ParseStatementQueryTicket(any));
+    return DoGetStatement(context, command, stream);
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoGetPreparedStatement(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCatalogs>()) {
+    return DoGetCatalogs(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSchemas>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSchemas internal_command, ParseCommandGetSchemas(any));
+    return DoGetSchemas(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetTables>()) {
+    ARROW_ASSIGN_OR_RAISE(GetTables command, ParseCommandGetTables(any));
+    return DoGetTables(context, command, stream);
+  } else if (any.Is<pb::sql::CommandGetTableTypes>()) {
+    return DoGetTableTypes(context, stream);
+  } else if (any.Is<pb::sql::CommandGetSqlInfo>()) {
+    ARROW_ASSIGN_OR_RAISE(GetSqlInfo internal_command,
+                          ParseCommandGetSqlInfo(any, sql_info_id_to_result_));
+    return DoGetSqlInfo(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetPrimaryKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetPrimaryKeys internal_command,
+                          ParseCommandGetPrimaryKeys(any));
+    return DoGetPrimaryKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetExportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetExportedKeys internal_command,
+                          ParseCommandGetExportedKeys(any));
+    return DoGetExportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetImportedKeys>()) {
+    ARROW_ASSIGN_OR_RAISE(GetImportedKeys internal_command,
+                          ParseCommandGetImportedKeys(any));
+    return DoGetImportedKeys(context, internal_command, stream);
+  } else if (any.Is<pb::sql::CommandGetCrossReference>()) {
+    ARROW_ASSIGN_OR_RAISE(GetCrossReference internal_command,
+                          ParseCommandGetCrossReference(any));
+    return DoGetCrossReference(context, internal_command, stream);
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::DoPut(const ServerCallContext& context,
+                                  std::unique_ptr<FlightMessageReader> reader,
+                                  std::unique_ptr<FlightMetadataWriter> writer) {
+  const FlightDescriptor& request = reader->descriptor();
+
+  google::protobuf::Any any;
+  if (!any.ParseFromArray(request.cmd.data(), static_cast<int>(request.cmd.size()))) {
+    return Status::Invalid("Unable to parse command.");
+  }
+
+  if (any.Is<pb::sql::CommandStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(StatementUpdate internal_command,
+                          ParseCommandStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count,
+                          DoPutCommandStatementUpdate(context, internal_command, reader))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  } else if (any.Is<pb::sql::CommandPreparedStatementQuery>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementQuery internal_command,
+                          ParseCommandPreparedStatementQuery(any));
+    return DoPutPreparedStatementQuery(context, internal_command, reader.get(),
+                                       writer.get());
+  } else if (any.Is<pb::sql::CommandPreparedStatementUpdate>()) {
+    ARROW_ASSIGN_OR_RAISE(PreparedStatementUpdate internal_command,
+                          ParseCommandPreparedStatementUpdate(any));
+    ARROW_ASSIGN_OR_RAISE(auto record_count, DoPutPreparedStatementUpdate(
+                                                 context, internal_command, reader.get()))
+
+    pb::sql::DoPutUpdateResult result;
+    result.set_record_count(record_count);
+
+    const std::shared_ptr<Buffer>& buffer =
+        Buffer::FromString(result.SerializeAsString());
+    ARROW_RETURN_NOT_OK(writer->WriteMetadata(*buffer));
+
+    return Status::OK();
+  }
+
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::ListActions(const ServerCallContext& context,
+                                        std::vector<ActionType>* actions) {
+  *actions = {FlightSqlServerBase::kCreatePreparedStatementActionType,
+              FlightSqlServerBase::kClosePreparedStatementActionType};
+  return Status::OK();
+}
+
+Status FlightSqlServerBase::DoAction(const ServerCallContext& context,
+                                     const Action& action,
+                                     std::unique_ptr<ResultStream>* result_stream) {
+  if (action.type == FlightSqlServerBase::kCreatePreparedStatementActionType.type) {
+    google::protobuf::Any any_command;
+    if (!any_command.ParseFromArray(action.body->data(),
+                                    static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionCreatePreparedStatementRequest internal_command,
+                          ParseActionCreatePreparedStatementRequest(any_command));
+    ARROW_ASSIGN_OR_RAISE(auto result, CreatePreparedStatement(context, internal_command))
+
+    pb::sql::ActionCreatePreparedStatementResult action_result;
+    action_result.set_prepared_statement_handle(result.prepared_statement_handle);
+    if (result.dataset_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_dataset_schema,
+                            ipc::SerializeSchema(*result.dataset_schema))
+      action_result.set_dataset_schema(serialized_dataset_schema->ToString());
+    }
+    if (result.parameter_schema != nullptr) {
+      ARROW_ASSIGN_OR_RAISE(auto serialized_parameter_schema,
+                            ipc::SerializeSchema(*result.parameter_schema))
+      action_result.set_parameter_schema(serialized_parameter_schema->ToString());
+    }
+
+    google::protobuf::Any any;
+    any.PackFrom(action_result);
+
+    auto buf = Buffer::FromString(any.SerializeAsString());
+    *result_stream = std::unique_ptr<ResultStream>(new SimpleResultStream({Result{buf}}));
+
+    return Status::OK();
+  } else if (action.type == FlightSqlServerBase::kClosePreparedStatementActionType.type) {
+    google::protobuf::Any any;
+    if (!any.ParseFromArray(action.body->data(), static_cast<int>(action.body->size()))) {
+      return Status::Invalid("Unable to parse action.");
+    }
+
+    ARROW_ASSIGN_OR_RAISE(ActionClosePreparedStatementRequest internal_command,
+                          ParseActionClosePreparedStatementRequest(any));
+
+    return ClosePreparedStatement(context, internal_command, result_stream);
+  }
+  return Status::Invalid("The defined request is invalid.");
+}
+
+Status FlightSqlServerBase::GetFlightInfoCatalogs(const ServerCallContext& context,
+                                                  const FlightDescriptor& descriptor,
+                                                  std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::DoGetCatalogs(const ServerCallContext& context,
+                                          std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetCatalogs not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoStatement(const ServerCallContext& context,
+                                                   const StatementQuery& command,
+                                                   const FlightDescriptor& descriptor,
+                                                   std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetStatement(const ServerCallContext& context,
+                                           const StatementQueryTicket& command,
+                                           std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    const FlightDescriptor& descriptor, std::unique_ptr<FlightInfo>* info) {
+  return Status::NotImplemented("GetFlightInfoPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::DoGetPreparedStatement(
+    const ServerCallContext& context, const PreparedStatementQuery& command,
+    std::unique_ptr<FlightDataStream>* result) {
+  return Status::NotImplemented("DoGetPreparedStatement not implemented");
+}
+
+Status FlightSqlServerBase::GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                                 const GetSqlInfo& command,
+                                                 const FlightDescriptor& descriptor,
+                                                 std::unique_ptr<FlightInfo>* info) {
+  assert(info != nullptr);
+
+  if (sql_info_id_to_result_.empty()) {
+    return Status::NotImplemented("GetFlightInfoSqlInfo not implemented");
+  }
+
+  std::vector<FlightEndpoint> endpoints{FlightEndpoint{{descriptor.cmd}, {}}};
+  ARROW_ASSIGN_OR_RAISE(auto result, FlightInfo::Make(*SqlSchema::GetSqlInfoSchema(),
+                                                      descriptor, endpoints, -1, -1))
+
+  *info = std::unique_ptr<FlightInfo>(new FlightInfo(result));
+
+  return Status::OK();
+}
+
+void FlightSqlServerBase::RegisterSqlInfo(int32_t id, const SqlInfoResult& result) {
+  sql_info_id_to_result_[id] = result;
+}
+
+Status FlightSqlServerBase::DoGetSqlInfo(const ServerCallContext& context,
+                                         const GetSqlInfo& command,
+                                         std::unique_ptr<FlightDataStream>* result) {
+  assert(result != nullptr);

Review comment:
       ```suggestion
     DCHECK(result);
   ```

##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,251 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  virtual Status GetFlightInfo(const FlightCallOptions& options,

Review comment:
       Actually, why not make GetFlightInfoForCommand and GetFlightInfo protected methods?

##########
File path: cpp/src/arrow/flight/flight_sql/sql_info_util.h
##########
@@ -0,0 +1,84 @@
+// Licensed to the Apache Software Foundation (ASF) under one

Review comment:
       If we want to expose the typedefs, we can make a `types.h` like Flight does.

##########
File path: cpp/src/arrow/flight/flight_sql/server_test.cc
##########
@@ -0,0 +1,774 @@
+// 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/flight_sql/server.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/api.h"
+#include "arrow/flight/flight_sql/FlightSql.pb.h"
+#include "arrow/flight/flight_sql/api.h"
+#include "arrow/flight/flight_sql/example/sqlite_server.h"
+#include "arrow/flight/test_util.h"
+#include "arrow/flight/types.h"
+#include "arrow/testing/gtest_util.h"
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+/// \brief Auxiliary boost::variant visitor used to assert that GetSqlInfo's values are
+/// correctly placed on its DenseUnionArray
+class SqlInfoDenseUnionValidator : public boost::static_visitor<void> {
+ private:
+  const DenseUnionScalar& data;
+
+ public:
+  /// \brief Asserts that the current DenseUnionScalar equals to given string value
+  void operator()(const std::string& string_value) const {
+    const auto& scalar = dynamic_cast<const StringScalar&>(*data.value);
+    ASSERT_EQ(string_value, scalar.ToString());
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given bool value
+  void operator()(const bool bool_value) const {
+    const auto& scalar = dynamic_cast<const BooleanScalar&>(*data.value);
+    ASSERT_EQ(bool_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int64_t value
+  void operator()(const int64_t bigint_value) const {
+    const auto& scalar = dynamic_cast<const Int64Scalar&>(*data.value);
+    ASSERT_EQ(bigint_value, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32_t value
+  void operator()(const int32_t int32_bitmask) const {
+    const auto& scalar = dynamic_cast<const Int32Scalar&>(*data.value);
+    ASSERT_EQ(int32_bitmask, scalar.value);
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given string list
+  void operator()(const string_list_t& string_list) const {
+    const auto& array = dynamic_cast<const StringArray&>(
+        *(dynamic_cast<const ListScalar&>(*data.value).value));
+
+    ASSERT_EQ(string_list.size(), array.length());
+
+    for (size_t index = 0; index < string_list.size(); index++) {
+      ASSERT_EQ(string_list[index], array.GetString(index));
+    }
+  }
+
+  /// \brief Asserts that the current DenseUnionScalar equals to given int32 to int32 list
+  /// map.
+  void operator()(const int32_to_int32_list_t& int32_to_int32_list) const {
+    const auto& struct_array = dynamic_cast<const StructArray&>(
+        *dynamic_cast<const MapScalar&>(*data.value).value);
+    const auto& keys = dynamic_cast<const Int32Array&>(*struct_array.field(0));
+    const auto& values = dynamic_cast<const ListArray&>(*struct_array.field(1));
+
+    // Assert that the given map has the right size
+    ASSERT_EQ(int32_to_int32_list.size(), keys.length());
+
+    // For each element on given MapScalar, assert it matches the argument
+    for (int i = 0; i < keys.length(); i++) {
+      ASSERT_OK_AND_ASSIGN(const auto& key_scalar, keys.GetScalar(i));
+      int32_t sql_info_id = dynamic_cast<const Int32Scalar&>(*key_scalar).value;
+
+      // Assert the key (SqlInfo id) exists
+      ASSERT_TRUE(int32_to_int32_list.count(sql_info_id));
+
+      const std::vector<int32_t>& expected_int32_list =
+          int32_to_int32_list.at(sql_info_id);
+
+      // Assert the value (int32 list) has the correct size
+      ASSERT_EQ(expected_int32_list.size(), values.value_length(i));
+
+      // For each element on current ListScalar, assert it matches with the argument
+      for (size_t j = 0; j < expected_int32_list.size(); j++) {
+        ASSERT_OK_AND_ASSIGN(auto list_item_scalar,
+                             values.values()->GetScalar(values.value_offset(i) + j));
+        const auto& list_item = dynamic_cast<const Int32Scalar&>(*list_item_scalar).value;
+        ASSERT_EQ(expected_int32_list[j], list_item);
+      }
+    }
+  }
+
+  explicit SqlInfoDenseUnionValidator(const DenseUnionScalar& data) : data(data) {}
+};
+
+std::unique_ptr<TestServer> server;
+std::unique_ptr<FlightSqlClient> sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server.reset(new TestServer("flight_sql_test_server"));
+    server->Start();
+    for (int i = 0; i < 100; i++) {
+      std::this_thread::sleep_for(std::chrono::milliseconds(10));
+      if (server->IsRunning()) {
+        break;
+      }
+    }
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client.reset(new FlightSqlClient(std::move(client)));
+  }
+
+  void TearDown() override {
+    sql_client.reset();
+    server->Stop();
+    server.reset();
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->Execute({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array = ArrayFromJSON(int64(), R"([1, 2, 3])");
+  std::shared_ptr<Array> keyname_array =
+      ArrayFromJSON(utf8(), R"(["one", "zero", "negative one"])");
+  std::shared_ptr<Array> value_array = ArrayFromJSON(int64(), R"([1, 0, -1])");
+  std::shared_ptr<Array> foreignId_array = ArrayFromJSON(int64(), R"([1, 1, 1])");
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::vector<std::string> table_types;
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {"foreignTable", "intTable", "sqlite_sequence"}, &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableFilter) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithTableTypesFilter) {
+  std::vector<std::string> table_types{"index"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_TRUE(table->schema()->Equals(SqlSchema::GetTablesSchema()));
+
+  ASSERT_EQ(table->num_rows(), 0);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithUnexistenceTableTypeFilter) {
+  std::vector<std::string> table_types{"table"};
+
+  ASSERT_OK_AND_ASSIGN(
+      auto flight_info,
+      sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 3))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 3))
+  std::shared_ptr<Array> table_name;
+  ArrayFromVector<StringType, std::string>(
+      {
+          "foreignTable",
+          "intTable",
+          "sqlite_sequence",
+      },
+      &table_name);
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table", "table", "table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTablesWithIncludedSchemas) {
+  std::vector<std::string> table_types;
+
+  std::string table_filter_pattern = "int%";
+  ASSERT_OK_AND_ASSIGN(auto flight_info,
+                       sql_client->GetTables({}, nullptr, nullptr, &table_filter_pattern,
+                                             true, table_types));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  ASSERT_OK_AND_ASSIGN(auto catalog_name, MakeArrayOfNull(utf8(), 1))
+  ASSERT_OK_AND_ASSIGN(auto schema_name, MakeArrayOfNull(utf8(), 1))
+  std::shared_ptr<Array> table_name;
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"intTable"}, &table_name);
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Schema> schema_table = arrow::schema(
+      {arrow::field("id", int64(), true), arrow::field("keyName", utf8(), true),
+       arrow::field("value", int64(), true), arrow::field("foreignId", int64(), true)});
+
+  const arrow::Result<std::shared_ptr<Buffer>>& value =
+      ipc::SerializeSchema(*schema_table);
+  std::shared_ptr<Buffer> schema_buffer;
+
+  ASSERT_OK_AND_ASSIGN(schema_buffer, value);
+  std::shared_ptr<Array> table_schema;
+
+  ArrayFromVector<BinaryType, std::string>({schema_buffer->ToString()}, &table_schema);
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetTablesSchemaWithIncludedSchema(),
+                  {catalog_name, schema_name, table_name, table_type, table_schema});
+
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandGetCatalogs) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetCatalogs({}));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema = SqlSchema::GetCatalogsSchema();
+
+  ASSERT_TRUE(table->schema()->Equals(*expected_schema));
+  ASSERT_EQ(0, table->num_rows());
+}
+
+TEST(TestFlightSqlServer, TestCommandGetSchemas) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetSchemas({}, NULLPTR, NULLPTR));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema = SqlSchema::GetSchemasSchema();
+
+  ASSERT_TRUE(table->schema()->Equals(*expected_schema));
+  ASSERT_EQ(0, table->num_rows());
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTableTypes) {
+  ASSERT_OK_AND_ASSIGN(auto flight_info, sql_client->GetTableTypes({}));
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  std::shared_ptr<Array> table_type;
+  ArrayFromVector<StringType, std::string>({"table"}, &table_type);
+
+  const std::shared_ptr<Table>& expected_table =
+      Table::Make(SqlSchema::GetTableTypesSchema(), {table_type});
+  AssertTablesEqual(*expected_table, *table);
+}
+
+TEST(TestFlightSqlServer, TestCommandStatementUpdate) {
+  int64_t result;
+  ASSERT_OK_AND_ASSIGN(result,
+                       sql_client->ExecuteUpdate(
+                           {},
+                           "INSERT INTO intTable (keyName, value) VALUES "
+                           "('KEYNAME1', 1001), ('KEYNAME2', 1002), ('KEYNAME3', 1003)"));
+  ASSERT_EQ(3, result);
+
+  ASSERT_OK_AND_ASSIGN(result, sql_client->ExecuteUpdate(
+                                   {},
+                                   "UPDATE intTable SET keyName = 'KEYNAME1' "
+                                   "WHERE keyName = 'KEYNAME2' OR keyName = 'KEYNAME3'"));
+  ASSERT_EQ(2, result);
+
+  ASSERT_OK_AND_ASSIGN(
+      result,
+      sql_client->ExecuteUpdate({}, "DELETE FROM intTable WHERE keyName = 'KEYNAME1'"));
+  ASSERT_EQ(3, result);
+}
+
+TEST(TestFlightSqlServer, TestCommandPreparedStatementQuery) {
+  ASSERT_OK_AND_ASSIGN(auto prepared_statement,
+                       sql_client->Prepare({}, "SELECT * FROM intTable"));
+
+  ASSERT_OK_AND_ASSIGN(auto flight_info, prepared_statement->Execute());
+
+  ASSERT_OK_AND_ASSIGN(auto stream,
+                       sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  std::shared_ptr<Array> id_array;
+  std::shared_ptr<Array> keyname_array;
+  std::shared_ptr<Array> value_array;
+  std::shared_ptr<Array> foreignId_array;
+  ArrayFromVector<Int64Type, std::int64_t>({1, 2, 3}, &id_array);
+  ArrayFromVector<StringType, std::string>({"one", "zero", "negative one"},
+                                           &keyname_array);
+  ArrayFromVector<Int64Type, std::int64_t>({1, 0, -1}, &value_array);
+  ArrayFromVector<Int64Type, std::int64_t>({1, 1, 1}, &foreignId_array);

Review comment:
       nit: can we stick to one of ArrayFromJSON or ArrayFromVector? (MakeArrayOfNull is fine.)

##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,258 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, const std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  /// \brief Retrieve the flightInfo. It is public because it is been used by the
+  /// anonymous function GetFlightInfoForCommand.

Review comment:
       GetFlightInfoForCommand is internal, no need to mention it.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] github-actions[bot] commented on pull request #11507: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
github-actions[bot] commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-948760815


   <!--
     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.
   -->
   
   Thanks for opening a pull request!
   
   If this is not a [minor PR](https://github.com/apache/arrow/blob/master/CONTRIBUTING.md#Minor-Fixes). Could you open an issue for this pull request on JIRA? https://issues.apache.org/jira/browse/ARROW
   
   Opening JIRAs ahead of time contributes to the [Openness](http://theapacheway.com/open/#:~:text=Openness%20allows%20new%20users%20the,must%20happen%20in%20the%20open.) of the Apache Arrow project.
   
   Then could you also rename pull request title in the following format?
   
       ARROW-${JIRA_ID}: [${COMPONENT}] ${SUMMARY}
   
   or
   
       MINOR: [${COMPONENT}] ${SUMMARY}
   
   See also:
   
     * [Other pull requests](https://github.com/apache/arrow/pulls/)
     * [Contribution Guidelines - How to contribute patches](https://arrow.apache.org/docs/developers/contributing.html#how-to-contribute-patches)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm closed pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm closed pull request #11507:
URL: https://github.com/apache/arrow/pull/11507


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r759645454



##########
File path: cpp/src/arrow/flight/sql/example/sqlite_server.h
##########
@@ -0,0 +1,357 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "arrow/api.h"
+#include "arrow/flight/sql/FlightSql.pb.h"

Review comment:
       Sorry I missed this. We shouldn't expose the Protobufs here (that said, see ARROW-14771). It seems we should duplicate the enums in C++ (which will be tedious, unfortunately).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r763128465



##########
File path: cpp/src/arrow/flight/sql/example/sqlite_server.cc
##########
@@ -0,0 +1,684 @@
+// 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/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>

Review comment:
       Raising this again - iequals is used below, but not lexical_cast

##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name, then schema_name.
+ */
+message CommandGetSchemas {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, the pattern will not be used to narrow the search.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+}
+
+/*
+ * Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  table_type: utf8 not null,
+ *  [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema,
+ *                                           it is serialized as an IPC message.)
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, then table_type, followed by table_schema if requested.
+ */
+message CommandGetTables {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, all schemas matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+
+  /*
+   * Specifies a filter pattern for tables to search for.
+   * When no table_name_filter_pattern is provided, all tables matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string table_name_filter_pattern = 3;
+
+  // Specifies a filter of table types which must match.
+  repeated string table_types = 4;
+
+  // Specifies if the schema should be returned for found tables.
+  bool include_schema = 5;
+}
+
+/*
+ * Represents a request to retrieve the list of table types on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  table_type: utf8 not null
+ * >
+ * The returned data should be ordered by table_type.
+ */
+message CommandGetTableTypes {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the primary keys of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  column_name: utf8 not null,
+ *  key_name: utf8,
+ *  key_sequence: int not null
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, key_name, then key_sequence.
+ */
+message CommandGetPrimaryKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the table to get the primary keys for.
+  string table = 3;
+}
+
+enum UpdateDeleteRules {
+  CASCADE = 0;
+  RESTRICT = 1;
+  SET_NULL = 2;
+  NO_ACTION = 3;
+  SET_DEFAULT = 4;
+}
+
+/*
+ * Represents a request to retrieve a description of the foreign key columns that reference the given table's
+ * primary key columns (the foreign keys exported by a table) of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by fk_catalog_name, fk_schema_name, fk_table_name, fk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions declared on UpdateDeleteRules enum.
+ */
+message CommandGetExportedKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the foreign key table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the foreign key table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the foreign key table to get the foreign keys for.
+  string table = 3;
+}
+
+/*
+ * Represents a request to retrieve the foreign keys of a table on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by pk_catalog_name, pk_schema_name, pk_table_name, pk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions:
+ *    - 0 = CASCADE
+ *    - 1 = RESTRICT
+ *    - 2 = SET NULL
+ *    - 3 = NO ACTION
+ *    - 4 = SET DEFAULT
+ */
+message CommandGetImportedKeys {
+  option (experimental) = true;
+
+  /*
+   * Specifies the catalog to search for the primary key table.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies the schema to search for the primary key table.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string schema = 2;
+
+  // Specifies the primary key table to get the foreign keys for.
+  string table = 3;
+}
+
+/*
+ * Represents a request to retrieve a description of the foreign key columns in the given foreign key table that
+ * reference the primary key or the columns representing a unique constraint of the parent table (could be the same
+ * or a different table) on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  pk_catalog_name: utf8,
+ *  pk_schema_name: utf8,
+ *  pk_table_name: utf8 not null,
+ *  pk_column_name: utf8 not null,
+ *  fk_catalog_name: utf8,
+ *  fk_schema_name: utf8,
+ *  fk_table_name: utf8 not null,
+ *  fk_column_name: utf8 not null,
+ *  key_sequence: int not null,
+ *  fk_key_name: utf8,
+ *  pk_key_name: utf8,
+ *  update_rule: uint1 not null,
+ *  delete_rule: uint1 not null
+ * >
+ * The returned data should be ordered by pk_catalog_name, pk_schema_name, pk_table_name, pk_key_name, then key_sequence.
+ * update_rule and delete_rule returns a byte that is equivalent to actions:
+ *    - 0 = CASCADE
+ *    - 1 = RESTRICT
+ *    - 2 = SET NULL
+ *    - 3 = NO ACTION
+ *    - 4 = SET DEFAULT
+ */
+message CommandGetCrossReference {
+  option (experimental) = true;
+
+  /**
+   * The catalog name where the parent table is.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string pk_catalog = 1;
+
+  /**
+   * The Schema name where the parent table is.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string pk_schema = 2;
+
+  /**
+   * The parent table name. It cannot be null.
+   */
+  string pk_table = 3;
+
+  /**
+   * The catalog name where the foreign table is.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string fk_catalog = 4;
+
+  /**
+   * The schema name where the foreign table is.
+   * An empty string retrieves those without a schema.
+   * If omitted the schema name should not be used to narrow the search.
+   */
+  optional string fk_schema = 5;
+
+  /**
+   * The foreign table name. It cannot be null.
+   */
+  string fk_table = 6;
+}
+
+// SQL Execution Action Messages
+
+/*
+ * Request message for the "CreatePreparedStatement" action on a Flight SQL enabled backend.
+ */
+message ActionCreatePreparedStatementRequest {
+  option (experimental) = true;
+
+  // The valid SQL string to create a prepared statement for.
+  string query = 1;
+}
+
+/*
+ * Wrap the result of a "GetPreparedStatement" action.
+ *
+ * The resultant PreparedStatement can be closed either:
+ * - Manually, through the "ClosePreparedStatement" action;
+ * - Automatically, by a server timeout.
+ */
+message ActionCreatePreparedStatementResult {
+  option (experimental) = true;
+
+  // Opaque handle for the prepared statement on the server.
+  bytes prepared_statement_handle = 1;
+
+  // If a result set generating query was provided, dataset_schema contains the 
+  // schema of the dataset as described in Schema.fbs::Schema, it is serialized as an IPC message.
+  bytes dataset_schema = 2;
+
+  // If the query provided contained parameters, parameter_schema contains the 
+  // schema of the expected parameters as described in Schema.fbs::Schema, it is serialized as an IPC message.
+  bytes parameter_schema = 3;
+}
+
+/*
+ * Request message for the "ClosePreparedStatement" action on a Flight SQL enabled backend.
+ * Closes server resources associated with the prepared statement handle.
+ */
+message ActionClosePreparedStatementRequest {
+  option (experimental) = true;
+
+  // Opaque handle for the prepared statement on the server.
+  bytes prepared_statement_handle = 1;
+}
+
+
+// SQL Execution Messages.
+
+/*
+ * Represents a SQL query. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the query.
+ */
+message CommandStatementQuery {
+  option (experimental) = true;
+
+  // The SQL syntax.
+  string query = 1;
+}
+
+/**
+ * Represents a ticket resulting from GetFlightInfo with a CommandStatementQuery.
+ * This should be treated as an opaque value, that is, clients should not attempt to parse this.
+ */
+message TicketStatementQuery {
+  option (experimental) = true;
+
+  // Unique identifier for the instance of the statement to execute.
+  bytes statement_handle = 1;

Review comment:
       CC @rafael-telles this and https://github.com/apache/arrow/pull/11507/files#r756031574 should be added to the docstrings here.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734722860



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       A very strange bug occurred when we tried to link them together and also when we tried following the same approach as Flight (through `protocol_internal.cc`), my understanding of what went wrong is this:
   
   The problem was that as Arrow Flight implicitly static-links Protobuf (when compiling protocol_internal.cc), Arrow Flight SQL was linking it too by the same means and this ended up causing a one definition rule violation on an internal symbol of protobuf (google::protobuf::internal::GetEmptyStringAlreadyInited())
   
   Other person reported the exactly same issue here: https://github.com/protocolbuffers/protobuf/issues/6031




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734742855



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       Yes, that was templated to support putting a mock client in for tests.
   
   If I'm reading this right, the suggestion would be to have:
   - client.h methods just be declarations and take in a FlightClientImpl*
   - create a client_internal.h that defines what FlightClientImpl can do.
   - Provide two .cc's that implement FlightClientImpl, one with the logic for a real FlightClient and one for a mock FlightClient. The .cc used will depend on if building for release or for tests.
   - Provide a .cc for FlightSqlClient that invokes the FlightClientImpl.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734762969



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       @lidavidm , that would be to load FlightSQL protobuf on Flight's `protocol_internal.cc`?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r740395586



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,116 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")

Review comment:
       Thanks for fixing this.

##########
File path: cpp/src/arrow/flight/flight_sql/test_app_cli.cc
##########
@@ -0,0 +1,194 @@
+// 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/array/builder_binary.h>
+#include <arrow/array/builder_primitive.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight_sql/api.h>
+#include <arrow/io/memory.h>
+#include <arrow/pretty_print.h>
+#include <arrow/status.h>
+#include <arrow/table.h>
+#include <gflags/gflags.h>
+
+#include <boost/algorithm/string.hpp>
+#include <iostream>
+#include <memory>
+
+using arrow::Result;
+using arrow::Schema;
+using arrow::Status;
+using arrow::flight::ClientAuthHandler;
+using arrow::flight::FlightCallOptions;
+using arrow::flight::FlightClient;
+using arrow::flight::FlightDescriptor;
+using arrow::flight::FlightEndpoint;
+using arrow::flight::FlightInfo;
+using arrow::flight::FlightStreamChunk;
+using arrow::flight::FlightStreamReader;
+using arrow::flight::Location;
+using arrow::flight::Ticket;
+using arrow::flight::sql::FlightSqlClient;
+
+DEFINE_string(host, "localhost", "Host to connect to");
+DEFINE_int32(port, 32010, "Port to connect to");
+DEFINE_string(username, "", "Username");
+DEFINE_string(password, "", "Password");
+
+DEFINE_string(command, "", "Method to run");
+DEFINE_string(query, "", "Query");
+DEFINE_string(catalog, "", "Catalog");
+DEFINE_string(schema, "", "Schema");
+DEFINE_string(table, "", "Table");
+
+Status PrintResultsForEndpoint(FlightSqlClient& client,
+                               const FlightCallOptions& call_options,
+                               const FlightEndpoint& endpoint) {
+  ARROW_ASSIGN_OR_RAISE(auto stream, client.DoGet(call_options, endpoint.ticket));
+
+  const arrow::Result<std::shared_ptr<Schema>>& schema = stream->GetSchema();
+  ARROW_RETURN_NOT_OK(schema);
+
+  std::cout << "Schema:" << std::endl;
+  std::cout << schema->get()->ToString() << std::endl << std::endl;
+
+  std::cout << "Results:" << std::endl;
+
+  FlightStreamChunk chunk;
+  int64_t num_rows = 0;
+
+  while (true) {
+    ARROW_RETURN_NOT_OK(stream->Next(&chunk));
+    if (!(chunk.data != nullptr)) {
+      break;
+    }
+    std::cout << chunk.data->ToString() << std::endl;
+    num_rows += chunk.data->num_rows();
+  }
+
+  std::cout << "Total: " << num_rows << std::endl;
+
+  return Status::OK();
+}
+
+Status PrintResults(FlightSqlClient& client, const FlightCallOptions& call_options,
+                    const std::unique_ptr<FlightInfo>& info) {
+  const std::vector<FlightEndpoint>& endpoints = info->endpoints();
+
+  for (size_t i = 0; i < endpoints.size(); i++) {
+    std::cout << "Results from endpoint " << i + 1 << " of " << endpoints.size()
+              << std::endl;
+    ARROW_RETURN_NOT_OK(PrintResultsForEndpoint(client, call_options, endpoints[i]));
+  }
+
+  return Status::OK();
+}
+
+Status RunMain() {
+  std::unique_ptr<FlightClient> client;
+  Location location;
+  ARROW_RETURN_NOT_OK(Location::ForGrpcTcp(FLAGS_host, FLAGS_port, &location));
+  ARROW_RETURN_NOT_OK(FlightClient::Connect(location, &client));
+
+  FlightCallOptions call_options;
+
+  if (!FLAGS_username.empty() || !FLAGS_password.empty()) {
+    Result<std::pair<std::string, std::string>> bearer_result =
+        client->AuthenticateBasicToken({}, FLAGS_username, FLAGS_password);
+    ARROW_RETURN_NOT_OK(bearer_result);
+
+    call_options.headers.push_back(bearer_result.ValueOrDie());
+  }
+
+  FlightSqlClient sqlClient(std::move(client));

Review comment:
       nit: sql_client




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735804753



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       Just to be clear, was this merging only the generated Protobuf into libarrow_flight, or all the new files? I think it needs to be the latter.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r743911807



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       This appears to fix it for me, by avoiding linking Protobuf in multiple times:
   
   @rafael-telles does this work for you?
   
   ```diff
   diff --git a/cpp/src/arrow/flight/CMakeLists.txt b/cpp/src/arrow/flight/CMakeLists.txt
   index 309e5a968..66776424e 100644
   --- a/cpp/src/arrow/flight/CMakeLists.txt
   +++ b/cpp/src/arrow/flight/CMakeLists.txt
   @@ -27,11 +27,14 @@ endif()
    
    if(ARROW_TEST_LINKAGE STREQUAL "static")
      set(ARROW_FLIGHT_TEST_LINK_LIBS
   -      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
   +      arrow_flight_static
   +      arrow_flight_testing_static
   +      ${ARROW_FLIGHT_STATIC_LINK_LIBS}
   +      gRPC::grpc++
          ${ARROW_TEST_LINK_LIBS})
    else()
      set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
   -                                  ${ARROW_TEST_LINK_LIBS})
   +                                  gRPC::grpc++ ${ARROW_TEST_LINK_LIBS})
    endif()
    
    # TODO(wesm): Protobuf shared vs static linking
   @@ -165,6 +168,7 @@ add_arrow_lib(arrow_flight
                  ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
                  SHARED_LINK_LIBS
                  arrow_shared
   +              SHARED_PRIVATE_LINK_LIBS
                  ${ARROW_FLIGHT_LINK_LIBS}
                  STATIC_LINK_LIBS
                  arrow_static
   diff --git a/cpp/src/arrow/flight/flight_sql/CMakeLists.txt b/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   index fd453ccc5..8fd852909 100644
   --- a/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   +++ b/cpp/src/arrow/flight/flight_sql/CMakeLists.txt
   @@ -36,7 +36,8 @@ set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENER
    
    add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
    
   -set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc client_internal.cc)
   +set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc client_internal.cc
   +                          "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
    
    add_arrow_lib(arrow_flight_sql
                  CMAKE_PACKAGE_NAME
   @@ -51,10 +52,13 @@ add_arrow_lib(arrow_flight_sql
                  "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
                  DEPENDENCIES
                  flight_sql_protobuf_gen
   +              toolchain
                  SHARED_LINK_FLAGS
                  ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
                  SHARED_LINK_LIBS
                  arrow_flight_shared
   +              SHARED_PRIVATE_LINK_LIBS
   +              ${ARROW_PROTOBUF_LIBPROTOBUF}
                  STATIC_LINK_LIBS
                  arrow_flight_static)
    
   @@ -75,7 +79,6 @@ target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
    add_arrow_test(flight_sql_client_test
                   SOURCES
                   client_test.cc
   -               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
                   STATIC_LINK_LIBS
                   ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
                   LABELS
   @@ -85,7 +88,6 @@ add_arrow_test(flight_sql_server_test
                   SOURCES
                   server_test.cc
                   client_internal.cc
   -               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
                   STATIC_LINK_LIBS
                   ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
                   LABELS
   @@ -102,8 +104,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
                     example/sqlite_statement.cc
                     example/sqlite_statement_batch_reader.cc
                     example/sqlite_server.cc
   -                 example/sqlite_tables_schema_batch_reader.cc
   -                 "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
   +                 example/sqlite_tables_schema_batch_reader.cc)
      target_link_libraries(flight_sql_test_server
                            PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}
                                    ${SQLite3_LIBRARIES})
   diff --git a/cpp/vcpkg.json b/cpp/vcpkg.json
   index 11ce5250d..1aee71eb8 100644
   --- a/cpp/vcpkg.json
   +++ b/cpp/vcpkg.json
   @@ -17,7 +17,9 @@
        "benchmark",
        "boost-filesystem",
        "boost-multiprecision",
   +    "boost-process",
        "boost-system",
   +    "boost-uuid",
        "brotli",
        "bzip2",
        "c-ares",
   @@ -40,8 +42,5 @@
        "zlib",
        "zstd"
      ],
   -  "overrides": [
   -    { "name": "gtest", "version": "1.10.0", "port-version": 4 }
   -  ],
   -  "builtin-baseline": "b5865bfeba430cd44063fc54a45a8861195a715f"
   +  "builtin-baseline": "85b31152df8da18be5ec2b0dbd7b39b0d2404db4"
    }
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r745860956



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Hey @lidavidm , thank you for the suggestions!
   I think we can do similar to the first suggestion:
   
   Make `FlightSqlClient` as...
   ```c++
   class ARROW_EXPORT FlightSqlClient {
    private:
     std::shared_ptr<FlightClient> client_;
   
    public:
     explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
   
     ~FlightSqlClient();
   
     virtual Status GetFlightInfo(const FlightCallOptions& options,
                          const FlightDescriptor& descriptor,
                          std::unique_ptr<FlightInfo>* info) {
       return client_->GetFlightInfo(options, descriptor, info);
     }
     
     // Do the same with other FlightClient methods called
   ```
   
   Then we can mock these virtual methods(only the ones we simply forward to FlightClient) from FlightSqlClient instead of FlightClient/FlightClientImpl on `client_test.cc`.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746036864



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Done @lidavidm !




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746834782



##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,251 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  virtual Status GetFlightInfo(const FlightCallOptions& options,

Review comment:
       Ah, ok, I see now, thank you. Can we document this one similarly to the wrappers for DoGet et. al. above?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r745680774



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Ok, sorry, can we avoid using `FlightClientImpl` like this? I don't think this will be maintainable/I think this will be brittle. We can do something like the following:
   
   - Make `FlightSqlClient` an abstract base class, with an implementation `template <typename Client> class FlightSqlClientImpl : public FlightSqlClient { ... };` in `client_internal.h`. Then in `client.cc` we can define a factory method that instantiates and returns `FlightSqlClientImpl<FlightClient>` and in `client_test.cc` we can instantiate `FlightSqlClientImpl<MockedFlightClient>`. 
   
       This way the parameterization on the client impl is explicit and we are not relying on linker magic.
   - Alternatively, instead of mocking, we can just implement in-process dummy servers to provide the expected reply. This is definitely more code but avoids having to parameterize the client.
   - Alternatively, we can extract a `FlightClientInterface` or refactor `FlightClient` so it has virtual methods and is directly mockable.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jcralmeida commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jcralmeida commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746791261



##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,251 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  virtual Status GetFlightInfo(const FlightCallOptions& options,

Review comment:
       Becayse this function is used by an Anonymous function (GetFlightInfoForCommand).
   
   `arrow::Result<std::unique_ptr<FlightInfo>> GetFlightInfoForCommand(
       FlightSqlClient& client, const FlightCallOptions& options,
       const google::protobuf::Message& command) {
     const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
   
     std::unique_ptr<FlightInfo> flight_info;
     ARROW_RETURN_NOT_OK(client.GetFlightInfo(options, descriptor, &flight_info));
   
     return std::move(flight_info);
   }`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756031574



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name, then schema_name.
+ */
+message CommandGetSchemas {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, the pattern will not be used to narrow the search.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+}
+
+/*
+ * Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  table_type: utf8 not null,
+ *  [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema,
+ *                                           it is serialized as an IPC message.)
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, then table_type, followed by table_schema if requested.
+ */
+message CommandGetTables {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, all schemas matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+
+  /*
+   * Specifies a filter pattern for tables to search for.
+   * When no table_name_filter_pattern is provided, all tables matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string table_name_filter_pattern = 3;
+
+  // Specifies a filter of table types which must match.

Review comment:
       Ok, can you mention this briefly in this docstring?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756381625



##########
File path: cpp/src/arrow/flight/sql/server.cc
##########
@@ -0,0 +1,747 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include "arrow/flight/sql/server.h"
+
+#include <google/protobuf/any.pb.h>
+
+#include "arrow/api.h"
+#include "arrow/buffer.h"
+#include "arrow/flight/sql/FlightSql.pb.h"
+#include "arrow/flight/sql/sql_info_internal.h"
+#include "arrow/type.h"
+#include "arrow/util/logging.h"
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<std::string> CreateStatementQueryTicket(

Review comment:
       This is to disambiguate from `arrow::flight::Result`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-977140036


   Ah, @rafael-telles it seems there's a CI failure in "AMD64 Conda C++" (the others look spurious). Sorry for the delay on my end in triggering CI.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756380788



##########
File path: cpp/src/arrow/flight/sql/server.h
##########
@@ -0,0 +1,495 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/server.h"
+#include "arrow/flight/sql/server.h"
+#include "arrow/flight/sql/sql_info_types.h"
+#include "arrow/util/optional.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  std::vector<int32_t> info;
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;
+  util::optional<std::string> fk_catalog;
+  util::optional<std::string> fk_schema;
+  std::string fk_table;
+};
+
+struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+/// \brief A utility function to create a ticket for a statement query.
+///        Intended for Flight SQL server implementations.
+/// \param[in] statement_handle      The statement handle that will originate the ticket.
+/// \return                          The parsed ticket as an string.
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle);
+
+class ARROW_EXPORT FlightSqlServerBase : public FlightServerBase {
+ private:
+  SqlInfoResultMap sql_info_id_to_result_;
+
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType kCreatePreparedStatementActionType =
+      ActionType{"CreatePreparedStatement",
+                 "Creates a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionCreatePreparedStatementRequest\n"
+                 "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType kClosePreparedStatementActionType =
+      ActionType{"ClosePreparedStatement",
+                 "Closes a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionClosePreparedStatementRequest\n"
+                 "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQuery object containing the SQL statement.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const ServerCallContext& context,
+                                        const StatementQuery& command,
+                                        const FlightDescriptor& descriptor,
+                                        std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQueryTicket containing the statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetStatement(const ServerCallContext& context,
+                                const StatementQueryTicket& command,
+                                std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for executing an already created prepared statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPreparedStatement(const ServerCallContext& context,
+                                                const PreparedStatementQuery& command,
+                                                const FlightDescriptor& descriptor,
+                                                std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the prepared statement query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetPreparedStatement(const ServerCallContext& context,
+                                        const PreparedStatementQuery& command,

Review comment:
       This is also supported.
   The user can make a `DoPut` passing data to be bound to these placeholders, I think this is better described in the proposal: https://docs.google.com/document/d/1WQz32bDF06GgMdEYyzhakqUigBZkALFwDF2y1x3DTAI/edit#heading=h.2s8eyo1




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756376382



##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.

Review comment:
       (will push these changes later after internal review)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r752430087



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null

Review comment:
       Similar to catalogs, it depends on vendor/implementation. It is usually a namespace within the database or the database itself




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-983834919


   Hey @lidavidm ! 
   
   I am getting `Unsupported config option for services.ubuntu-r-only-r: 'extends'` when running `archery docker run conda-cpp`, maybe it's my docker-compose version (1.25.0) that doesn't support this... What version does CI use?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r748500837



##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_server.h
##########
@@ -0,0 +1,351 @@
+// 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.
+
+#pragma once
+
+#include <sqlite3.h>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight_sql/FlightSql.pb.h"
+#include "arrow/flight/flight_sql/example/sqlite_statement.h"
+#include "arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/flight_sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+namespace flight_sql_pb = arrow::flight::protocol::sql;
+
+/// \brief Gets the mapping from SQL info ids to SqlInfoResult instances.
+/// \return the cache.
+inline sql_info_id_to_result_t GetSqlInfoIdToResult() {

Review comment:
       This is being used on `server_test.cc` for assertions, would like to avoid building `sqlite_server.cc` and other files on the server test




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-969359333


   @emkornfield if you have time, since you have the context from the Flight SQL Java PR, would you be able to review this? If not, I can ask Antoine or someone else to take a look over the C++.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735830381



##########
File path: cpp/src/arrow/flight/flight-sql/client_impl.h
##########
@@ -0,0 +1,463 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/testing/gtest_util.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/message_lite.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T>
+FlightSqlClientT<T>::FlightSqlClientT(std::unique_ptr<T>& client) {
+  this->client = std::move(client);
+}
+
+template <class T>
+PreparedStatementT<T>::PreparedStatementT(
+    T* client_, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result_,
+    const FlightCallOptions& options_)
+    : client(client_),
+      prepared_statement_result(std::move(prepared_statement_result_)),
+      options(options_) {
+  is_closed = false;
+}
+
+template <class T>
+FlightSqlClientT<T>::~FlightSqlClientT() = default;
+
+template <class T>
+PreparedStatementT<T>::~PreparedStatementT<T>() {
+  Close();
+}
+
+inline FlightDescriptor GetFlightDescriptorForCommand(
+    const google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+template <class T>
+Status GetFlightInfoForCommand(const std::unique_ptr<T>& client,
+                               const FlightCallOptions& options,
+                               std::unique_ptr<FlightInfo>* flight_info,
+                               const google::protobuf::Message& command) {
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  return client->GetFlightInfo(options, descriptor, flight_info);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::Execute(const FlightCallOptions& options,
+                                    const std::string& query,
+                                    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandStatementQuery command;
+  command.set_query(query);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::ExecuteUpdate(const FlightCallOptions& options,
+                                          const std::string& query, int64_t* rows) const {
+  pb::sql::CommandStatementUpdate command;
+  command.set_query(query);
+
+  const FlightDescriptor& descriptor = GetFlightDescriptorForCommand(command);
+
+  std::unique_ptr<FlightStreamWriter> writer;
+  std::unique_ptr<FlightMetadataReader> reader;
+
+  ARROW_RETURN_NOT_OK(client->DoPut(options, descriptor, NULLPTR, &writer, &reader));
+
+  std::shared_ptr<Buffer> metadata;
+
+  const Status& status = reader->ReadMetadata(&metadata);
+
+  pb::sql::DoPutUpdateResult doPutUpdateResult;
+
+  Buffer* pBuffer = metadata.get();
+
+  const std::string& string = pBuffer->ToString();
+
+  doPutUpdateResult.ParseFrom<google::protobuf::MessageLite::kParse>(string);
+  *rows = doPutUpdateResult.record_count();
+
+  return Status::OK();
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetCatalogs(const FlightCallOptions& options,
+                                        std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetCatalogs command;
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetSchemas(const FlightCallOptions& options,
+                                       const std::string* catalog,
+                                       const std::string* schema_filter_pattern,
+                                       std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetSchemas command;
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+  if (schema_filter_pattern != NULLPTR) {
+    command.set_schema_filter_pattern(*schema_filter_pattern);
+  }
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetTables(const FlightCallOptions& options,
+                                      const std::string* catalog,
+                                      const std::string* schema_filter_pattern,
+                                      const std::string* table_filter_pattern,
+                                      bool include_schema,
+                                      std::vector<std::string>& table_types,
+                                      std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetTables command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema_filter_pattern != NULLPTR) {
+    command.set_schema_filter_pattern(*schema_filter_pattern);
+  }
+
+  if (table_filter_pattern != NULLPTR) {
+    command.set_table_name_filter_pattern(*table_filter_pattern);
+  }
+
+  command.set_include_schema(include_schema);
+
+  for (const std::string& table_type : table_types) {
+    command.add_table_types(table_type);
+  }
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetPrimaryKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table,
+    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetPrimaryKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetExportedKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table,
+    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetExportedKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetImportedKeys(
+    const FlightCallOptions& options, const std::string* catalog,
+    const std::string* schema, const std::string& table,
+    std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetImportedKeys command;
+
+  if (catalog != NULLPTR) {
+    command.set_catalog(*catalog);
+  }
+
+  if (schema != NULLPTR) {
+    command.set_schema(*schema);
+  }
+
+  command.set_table(table);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetCrossReference(
+    const FlightCallOptions& options, const std::string* pk_catalog,
+    const std::string* pk_schema, const std::string& pk_table,
+    const std::string* fk_catalog, const std::string* fk_schema,
+    const std::string& fk_table, std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetCrossReference command;
+
+  if (pk_catalog != NULLPTR) {
+    command.set_pk_catalog(*pk_catalog);
+  }
+  if (pk_schema != NULLPTR) {
+    command.set_pk_schema(*pk_schema);
+  }
+  command.set_pk_table(pk_table);
+
+  if (fk_catalog != NULLPTR) {
+    command.set_fk_catalog(*fk_catalog);
+  }
+  if (fk_schema != NULLPTR) {
+    command.set_fk_schema(*fk_schema);
+  }
+  command.set_fk_table(fk_table);
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::GetTableTypes(
+    const FlightCallOptions& options, std::unique_ptr<FlightInfo>* flight_info) const {
+  pb::sql::CommandGetTableTypes command;
+
+  return GetFlightInfoForCommand(client, options, flight_info, command);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::DoGet(const FlightCallOptions& options, const Ticket& ticket,
+                                  std::unique_ptr<FlightStreamReader>* stream) const {
+  return client->DoGet(options, ticket, stream);
+}
+
+template <class T>
+Status FlightSqlClientT<T>::Prepare(
+    const FlightCallOptions& options, const std::string& query,
+    std::shared_ptr<PreparedStatementT<T>>* prepared_statement) {
+  google::protobuf::Any command;
+  pb::sql::ActionCreatePreparedStatementRequest request;
+  request.set_query(query);
+  command.PackFrom(request);
+
+  Action action;
+  action.type = "CreatePreparedStatement";
+  action.body = Buffer::FromString(command.SerializeAsString());
+
+  std::unique_ptr<ResultStream> results;
+
+  ARROW_RETURN_NOT_OK(client->DoAction(options, action, &results));
+
+  std::unique_ptr<Result> result;
+  ARROW_RETURN_NOT_OK(results->Next(&result));
+
+  google::protobuf::Any prepared_result;
+
+  std::shared_ptr<Buffer> message = std::move(result->body);
+
+  prepared_result.ParseFromArray(message->data(), static_cast<int>(message->size()));
+
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+
+  prepared_result.UnpackTo(&prepared_statement_result);
+
+  prepared_statement->reset(
+      new PreparedStatementT<T>(client.get(), query, prepared_statement_result, options));
+
+  return Status::OK();
+}
+
+template <class T>
+Status PreparedStatementT<T>::Execute(std::unique_ptr<FlightInfo>* info) {
+  if (is_closed) {
+    return Status::Invalid("Statement already closed.");
+  }
+
+  pb::sql::CommandPreparedStatementQuery execute_query_command;
+
+  execute_query_command.set_prepared_statement_handle(
+      prepared_statement_result.prepared_statement_handle());
+
+  google::protobuf::Any any;
+  any.PackFrom(execute_query_command);
+
+  const std::string& string = any.SerializeAsString();
+  const FlightDescriptor descriptor = FlightDescriptor::Command(string);
+
+  if (parameter_binding && parameter_binding->num_rows() > 0) {
+    std::unique_ptr<FlightStreamWriter> writer;
+    std::unique_ptr<FlightMetadataReader> reader;
+    client->DoPut(options, descriptor, parameter_binding->schema(), &writer, &reader);

Review comment:
       Additionally if I fix this, I get a segfault in TestFlightSqlServer.TestCommandPreparedStatementUpdate.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r736010888



##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client = new FlightSqlClient(client);
+  }
+
+  void TearDown() override {
+    server->Stop();
+
+    free(server);
+    free(sql_client);

Review comment:
       Delete would work. Could also use unique_ptr and do an explicit release()




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735868334



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,107 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static

Review comment:
       This should use ARROW_FLIGHT_SQL_TEST_LINK_LIBS instead of hardcoding arrow_flight_sql_static

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,107 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
+                                                  ${GFLAGS_LIBRARIES})
+
+add_arrow_test(flight_sql_test
+        SOURCES
+        client_test.cc
+        server_test.cc
+        "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+        STATIC_LINK_LIBS
+        ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+        LABELS
+        "arrow_flight_sql")
+
+# Build test server for unit tests
+if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
+  find_package(SQLite3)
+  include_directories(${SQLite3_INCLUDE_DIRS})
+
+  add_executable(flight_sql_test_server
+          server.cc
+          test_server_cli.cc
+          example/sqlite_statement.cc
+          example/sqlite_statement_batch_reader.cc
+          example/sqlite_server.cc
+          example/sqlite_tables_schema_batch_reader.cpp
+          "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
+  target_link_libraries(flight_sql_test_server
+          PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}

Review comment:
       This should use ARROW_FLIGHT_SQL_TEST_LINK_LIBS instead of hardcoding arrow_flight_sql_static

##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,107 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
+                                                  ${GFLAGS_LIBRARIES})
+
+add_arrow_test(flight_sql_test
+        SOURCES
+        client_test.cc
+        server_test.cc
+        "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+        STATIC_LINK_LIBS
+        ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+        LABELS
+        "arrow_flight_sql")
+
+# Build test server for unit tests
+if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
+  find_package(SQLite3)
+  include_directories(${SQLite3_INCLUDE_DIRS})
+
+  add_executable(flight_sql_test_server
+          server.cc

Review comment:
       This shouldn't be here; it's already part of libarrow_flight_sql.so




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735851634



##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client = new FlightSqlClient(client);
+  }
+
+  void TearDown() override {
+    server->Stop();
+
+    free(server);
+    free(sql_client);
+  }
+};
+
+TEST(TestFlightSqlServer, TestCommandStatementQuery) {
+  std::unique_ptr<FlightInfo> flight_info;
+  ASSERT_OK(sql_client->Execute({}, "SELECT * FROM intTable", &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  const std::shared_ptr<Schema>& expected_schema =
+      arrow::schema({arrow::field("id", int64()), arrow::field("keyName", utf8()),
+                     arrow::field("value", int64()), arrow::field("foreignId", int64())});
+
+  DECLARE_ARRAY(id_array, Int64, ({1, 2, 3}));
+  DECLARE_ARRAY(keyname_array, String, ({"one", "zero", "negative one"}));
+  DECLARE_ARRAY(value_array, Int64, ({1, 0, -1}));
+  DECLARE_ARRAY(foreignId_array, Int64, ({1, 1, 1}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      expected_schema, {id_array, keyname_array, value_array, foreignId_array});
+
+  ASSERT_TRUE(expected_table->Equals(*table));
+}
+
+TEST(TestFlightSqlServer, TestCommandGetTables) {
+  std::unique_ptr<FlightInfo> flight_info;
+  std::vector<std::string> table_types;
+  ASSERT_OK(sql_client->GetTables({}, nullptr, nullptr, nullptr, false, table_types,
+                                  &flight_info));
+
+  std::unique_ptr<FlightStreamReader> stream;
+  ASSERT_OK(sql_client->DoGet({}, flight_info->endpoints()[0].ticket, &stream));
+
+  std::shared_ptr<Table> table;
+  ASSERT_OK(stream->ReadAll(&table));
+
+  DECLARE_NULL_ARRAY(catalog_name, String, 3);
+  DECLARE_NULL_ARRAY(schema_name, String, 3);
+  DECLARE_ARRAY(table_name, String,
+                ({
+                    "foreignTable",
+                    "intTable",
+                    "sqlite_sequence",
+                }));
+  DECLARE_ARRAY(table_type, String, ({"table", "table", "table"}));
+
+  const std::shared_ptr<Table>& expected_table = Table::Make(
+      SqlSchema::GetTablesSchema(), {catalog_name, schema_name, table_name, table_type});
+
+  ASSERT_TRUE(expected_table->Equals(*table));

Review comment:
       It also seems some of them don't fail if run in isolation.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r747640320



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       @lidavidm , this worked for me!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-976987275


   @pitrou do you have any other comments?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r752379100



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 

Review comment:
       This was discussed on the Java PR https://github.com/apache/arrow/pull/10906#discussion_r686800640




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-983857749


   Upgrading to 1.28.6 worked, thanks! Investigating the issue


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-955023238


   Regarding the Protobuf issue: I switched to vcpkg as that appears to be what you use, but I can't replicate still. What OS and compiler are you using? 


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-956457180


   > Regarding the Protobuf issue: I switched to vcpkg as that appears to be what you use, but I can't replicate still. What OS and compiler are you using?
   
   @lidavidm , yes, I am using vcpkg.
   My OS is Linux Mint 20.2, 
   cmake version 3.16.3
   g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
   gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
   
   Thanks for your help @lidavidm , please let me know if any other info is helpful! Working on the other comments
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742234375



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       I would expect that the object files for client.cc and client_test.cc both contain symbols for FlightClientImpl, and it just so happens that the linker picks the mock when compiling the test binary. 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-958006483


   Thanks. I'm still digging at this. vcpkg made a change recently that breaks the build, so I need to figure out that first…


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742331731



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       We are defining FlightClientImpl on `client_test.cc` and `client_internal.cc`, made sure that we are not building or linking them at any time on CMakeLists.txt




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm edited a comment on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm edited a comment on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-958006483


   Thanks. I'm still digging at this. vcpkg made a change recently that breaks the build, so I need to figure out that first…
   
   (In ARROW-14560)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742287999



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       The intent is that the library build and unit test build compile and link client.cc and client_test.cc respectively. These two files shouldn't be passed to the same linker run at once.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r757092565



##########
File path: cpp/src/arrow/flight/sql/example/sqlite_server.cc
##########
@@ -0,0 +1,684 @@
+// 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/example/sqlite_server.h"
+
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid_io.hpp>
+
+#include "arrow/api.h"
+#include "arrow/flight/sql/example/sqlite_statement.h"
+#include "arrow/flight/sql/example/sqlite_statement_batch_reader.h"
+#include "arrow/flight/sql/example/sqlite_tables_schema_batch_reader.h"
+#include "arrow/flight/sql/server.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+namespace {
+
+/// \brief Gets a SqliteStatement by given handle
+arrow::Result<std::shared_ptr<SqliteStatement>> GetStatementByHandle(
+    const std::map<boost::uuids::uuid, std::shared_ptr<SqliteStatement>>&
+        prepared_statements,
+    const std::string& handle) {
+  const auto& uuid = boost::lexical_cast<boost::uuids::uuid>(handle);
+
+  auto search = prepared_statements.find(uuid);
+  if (search == prepared_statements.end()) {
+    return Status::Invalid("Prepared statement not found");
+  }
+
+  return search->second;
+}
+
+std::string PrepareQueryForGetTables(const GetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.catalog.has_value()) {
+    table_query << " and catalog_name='" << command.catalog.value() << "'";
+  }
+
+  if (command.schema_filter_pattern.has_value()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern.value()
+                << "'";
+  }
+
+  if (command.table_name_filter_pattern.has_value()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern.value()
+                << "'";
+  }
+
+  if (!command.table_types.empty()) {
+    table_query << " and table_type IN (";
+    size_t size = command.table_types.size();
+    for (size_t i = 0; i < size; i++) {
+      table_query << "'" << command.table_types[i] << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt, FlightMessageReader* reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = static_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = static_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = static_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer = static_cast<StringScalar&>(*holder).value;
+            sqlite3_bind_text(stmt, c + 1, reinterpret_cast<const char*>(buffer->data()),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer = static_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+}  // namespace
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {

Review comment:
       Yes, `sqlite_type` here comes exactly as written in a `CREATE TABLE` statement.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-969299291


   @lidavidm , addressed the other comments as well.
   
   Thanks!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734733045



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       Hmm, unfortunate. Arrow can build against both static and dynamic protobuf. Looking at it, even when dynamically linking to Protobuf, the problematic `GetEmptyStringAlreadyInited` symbol mentioned in that issue still appears in libarrow_flight.so. 
   
   One way would be to fold FlightSQL into libarrow_flight.so/libarrow_flight.a, that way there is no need to have two separate libraries that can both link Protobuf. (I wonder how you are supposed to be able to build multiple things relying on Protobuf though…)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734742855



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       Yes, that was templated to support putting a mock client in for tests.
   
   If I'm reading this right, the suggestion would be to have:
   - client.h methods just be declarations and take in a FlightClientImpl*
   - create a client_internal.h that defines what FlightClientImpl can do.
   - Provide two .cc's that implement FlightClientImpl, one with the logic for a real FlightClient and one for a mock FlightClient.
   - Provide a .cc for FlightSqlClient that invokes the FlightClientImpl.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735867822



##########
File path: cpp/src/arrow/flight/flight-sql/example/sqlite_statement_batch_reader.cc
##########
@@ -0,0 +1,172 @@
+// 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/flight-sql/example/sqlite_statement_batch_reader.h"
+
+#include <sqlite3.h>
+
+#include "arrow/api.h"
+#include "arrow/flight/flight-sql/example/sqlite_statement.h"
+
+#define STRING_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const unsigned char* string = sqlite3_column_text(STMT, COLUMN);                   \
+    if (string == nullptr) {                                                           \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(string, bytes));          \
+    break;                                                                             \
+  }
+
+#define BINARY_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                    \
+    int bytes = sqlite3_column_bytes(STMT, COLUMN);                                    \
+    const void* blob = sqlite3_column_blob(STMT, COLUMN);                              \
+    if (blob == nullptr) {                                                             \
+      ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).AppendNull()); \
+      break;                                                                           \
+    }                                                                                  \
+    ARROW_RETURN_NOT_OK(                                                               \
+        (dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append((char*)blob, bytes));     \
+    break;                                                                             \
+  }
+
+#define INT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                    \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    sqlite3_int64 value = sqlite3_column_int64(STMT, COLUMN);                         \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define FLOAT_BUILDER_CASE(TYPE_CLASS, STMT, COLUMN)                                  \
+  case TYPE_CLASS##Type::type_id: {                                                   \
+    double value = sqlite3_column_double(STMT, COLUMN);                               \
+    ARROW_RETURN_NOT_OK((dynamic_cast<TYPE_CLASS##Builder&>(builder)).Append(value)); \
+    break;                                                                            \
+  }
+
+#define MAX_BATCH_SIZE 1024
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<Schema> SqliteStatementBatchReader::schema() const { return schema_; }
+
+SqliteStatementBatchReader::SqliteStatementBatchReader(
+    std::shared_ptr<SqliteStatement> statement, std::shared_ptr<Schema> schema)
+    : statement_(std::move(statement)), schema_(std::move(schema)) {

Review comment:
       Thank you so much @lidavidm , sorry we missed this




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jcralmeida commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jcralmeida commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746634383



##########
File path: cpp/src/arrow/flight/flight_sql/server.h
##########
@@ -0,0 +1,480 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <arrow/flight/server.h>
+#include <arrow/util/optional.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  // TODO: To be implemented.

Review comment:
       It's being taking care. We are in the final process of review what we've created.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r738735887



##########
File path: cpp/src/arrow/flight/flight-sql/client_impl.h
##########
@@ -0,0 +1,463 @@
+// 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/buffer.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/io/memory.h>
+#include <arrow/ipc/reader.h>
+#include <arrow/testing/gtest_util.h>
+#include <google/protobuf/any.pb.h>
+#include <google/protobuf/message_lite.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T>
+FlightSqlClientT<T>::FlightSqlClientT(std::unique_ptr<T>& client) {
+  this->client = std::move(client);
+}
+
+template <class T>
+PreparedStatementT<T>::PreparedStatementT(
+    T* client_, const std::string& query,
+    pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result_,
+    const FlightCallOptions& options_)
+    : client(client_),
+      prepared_statement_result(std::move(prepared_statement_result_)),
+      options(options_) {
+  is_closed = false;
+}
+
+template <class T>
+FlightSqlClientT<T>::~FlightSqlClientT() = default;
+
+template <class T>
+PreparedStatementT<T>::~PreparedStatementT<T>() {
+  Close();

Review comment:
       I think the best we can do is to log the error, as we can't throw exceptions on the destructor... Changed to do this




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r736867823



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \param schema   The parameter schema from the query.
+  /// \return         Status.
+  Status GetParameterSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \param schema   The ResultSet schema from the query.
+  /// \return         Status.
+  Status GetResultSetSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding_   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.
+  /// \return Status.
+  Status Close();
+
+  /// \brief Checks if the prepared statement is closed.
+  /// \return The state of the prepared statement.
+  bool IsClosed() const;
+};
+
+/// \brief Flight client with Flight SQL semantics.
+template <class T = arrow::flight::FlightClient>
+class FlightSqlClientT {
+ public:
+  explicit FlightSqlClientT(std::unique_ptr<T>& client);
+
+  ~FlightSqlClientT();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset
+  /// \return Status.
+  Status Execute(const FlightCallOptions& options, const std::string& query,
+                 std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] rows        The quantity of rows affected by the operation.
+  /// \return Status.
+  Status ExecuteUpdate(const FlightCallOptions& options, const std::string& query,
+                       int64_t* rows) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset.
+  /// \return Status.
+  Status GetCatalogs(const FlightCallOptions& options,
+                     std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \param[out] flight_info           The FlightInfo describing where to access the
+  ///                                   dataset.
+  /// \return Status.
+  Status GetSchemas(const FlightCallOptions& options, const std::string* catalog,
+                    const std::string* schema_filter_pattern,
+                    std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \param[out] stream the returned RecordBatchReader
+  /// \return Status
+  Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream) const;

Review comment:
       The convention in the Arrow codebase (following the Google C++ style guide) is to use `FlightSqlClient*` instead of a const reference, since the client is nominally "mutable".




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r738770207



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {
+  pb::sql::ActionCreatePreparedStatementResult prepared_statement_result;
+  std::shared_ptr<RecordBatch> parameter_binding;
+  FlightCallOptions options;
+  bool is_closed;
+  T* client;
+
+ public:
+  /// \brief Constructor for the PreparedStatement class.
+  /// \param[in] client   A raw pointer to FlightClient.
+  /// \param[in] query      The query that will be executed.
+  PreparedStatementT(
+      T* client, const std::string& query,
+      pb::sql::ActionCreatePreparedStatementResult& prepared_statement_result,
+      const FlightCallOptions& options);
+
+  /// \brief Default destructor for the PreparedStatement class.
+  /// The destructor will call the Close method from the class in order,
+  /// to send a request to close the PreparedStatement.
+  ~PreparedStatementT();
+
+  /// \brief Executes the prepared statement query on the server.
+  /// \param[in] call_options RPC-layer hints for this call.
+  /// \param[out] info        A FlightInfo object representing the stream(s) to fetch.
+  /// \return Status.
+  Status Execute(std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Executes the prepared statement update query on the server.
+  /// \param rows[out] The number of rows affected.
+  /// \return Status.
+  Status ExecuteUpdate(int64_t* rows);
+
+  /// \brief Retrieve the parameter schema from the query.
+  /// \param schema   The parameter schema from the query.
+  /// \return         Status.
+  Status GetParameterSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Retrieve the ResultSet schema from the query.
+  /// \param schema   The ResultSet schema from the query.
+  /// \return         Status.
+  Status GetResultSetSchema(std::shared_ptr<Schema>* schema);
+
+  /// \brief Set a RecordBatch that contains the parameters that will be bind.
+  /// \param parameter_binding_   The parameters that will be bind.
+  /// \return                     Status.
+  Status SetParameters(std::shared_ptr<RecordBatch> parameter_binding);
+
+  /// \brief Closes the prepared statement.
+  /// \param[in] options  RPC-layer hints for this call.
+  /// \return Status.
+  Status Close();
+
+  /// \brief Checks if the prepared statement is closed.
+  /// \return The state of the prepared statement.
+  bool IsClosed() const;
+};
+
+/// \brief Flight client with Flight SQL semantics.
+template <class T = arrow::flight::FlightClient>
+class FlightSqlClientT {
+ public:
+  explicit FlightSqlClientT(std::unique_ptr<T>& client);
+
+  ~FlightSqlClientT();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset
+  /// \return Status.
+  Status Execute(const FlightCallOptions& options, const std::string& query,
+                 std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \param[out] rows        The quantity of rows affected by the operation.
+  /// \return Status.
+  Status ExecuteUpdate(const FlightCallOptions& options, const std::string& query,
+                       int64_t* rows) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[out] flight_info The FlightInfo describing where to access the dataset.
+  /// \return Status.
+  Status GetCatalogs(const FlightCallOptions& options,
+                     std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \param[out] flight_info           The FlightInfo describing where to access the
+  ///                                   dataset.
+  /// \return Status.
+  Status GetSchemas(const FlightCallOptions& options, const std::string* catalog,
+                    const std::string* schema_filter_pattern,
+                    std::unique_ptr<FlightInfo>* flight_info) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \param[out] stream the returned RecordBatchReader
+  /// \return Status
+  Status DoGet(const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream) const;

Review comment:
       Got it!




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r753388765



##########
File path: cpp/src/arrow/CMakeLists.txt
##########
@@ -726,6 +726,10 @@ if(ARROW_FLIGHT)
   add_subdirectory(flight)
 endif()
 
+if(ARROW_FLIGHT_SQL)
+  add_subdirectory(flight/flight_sql)

Review comment:
       Changed to `flight/sql`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756342463



##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.h
##########
@@ -0,0 +1,87 @@
+// 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.
+
+#pragma once
+
+#include "arrow/flight/sql/sql_info_types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+/// \brief Auxiliary class used to populate GetSqlInfo's DenseUnionArray with different
+/// data types.
+class SqlInfoResultAppender {
+ public:
+  /// \brief Appends a string to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::string& value);
+
+  /// \brief Appends a bool to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(bool value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int64_t value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int32_t value);
+
+  /// \brief Appends a string list to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::vector<std::string>& value);
+
+  /// \brief Appends a int32 to int32 list map to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::unordered_map<int32_t, std::vector<int32_t>>& value);

Review comment:
       Hmm, I see, but this is a bit confusing. Why isn't it the same?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] kylepbit commented on pull request #11507: [ARROW-14421] [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
kylepbit commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-948816253


   @lidavidm - was just about to ping you on this but see that you already noticed it. Note that the C++ Server is missing a small bit of functionality but the client is there, so we should be in good shape to be near a vote.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742233667



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       We're defining FlightClientImpl twice and just using the fact that only one definition is visible at a time, trusting that the compiler/linker do the right thing. I'm not sure we can rely on this.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       I would expect that the object files for client.cc and client_test.cc both contain symbols for FlightClientImpl, and it just so happens that the linker picks the mock when compiling the test binary. 

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       That said, my understanding of this is shaky and maybe there is a good justification for why this works.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Both libarrow_flight_sql.so and client_test.cc.o have symbols for FlightClientImpl for me. That said, they're marked as weak symbols, and presumably the one in the program takes precedence. (Confirmed with LD_DEBUG.)
   
   This works and I'm not going to hold this up, however, it is rather magical and it's worth at least a comment explaining the intent of FlightClientImpl.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Both libarrow_flight_sql.so and client_test.cc.o have symbols for FlightClientImpl for me. That said, they're marked as weak symbols, and presumably the one in the program takes precedence. (Confirmed with LD_DEBUG.)
   
   <details>
   
   ```
   > nm -C src/arrow/flight/flight_sql/CMakeFiles/arrow-flight-sql-client-test.dir/client_test.cc.o | rg FlightClientImpl::DoPut
   0000000000000000 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   > nm -C debug/libarrow_flight_sql.so | rg FlightClientImpl::DoPut
   00000000000f1dc0 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   > nm -C debug/arrow-flight-sql-client-test | rg FlightClientImpl::DoPut
   000000000055b320 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   ```
   
   </details>
   
   This works and I'm not going to hold this up, however, it is rather magical and it's worth at least a comment explaining the intent of FlightClientImpl.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Er, sorry for the churn @rafael-telles but I think the latest commit is strictly worse. I think the situation is OK as-is so long as it's clearly documented (and I can't claim to be a linker expert or C++ standard expert so maybe this is all OK and I don't understand the reason why). I'm mostly just concerned that it's unclear what the intent is.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Perhaps, but even then, I would say that an implementation that requires very carefully linking objects together to be correct is not one we should go with.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       (Sorry - I want to try some alternative approaches but haven't found the time. At this rate it may be Friday before I can get into things…)

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       We're defining FlightClientImpl twice and just using the fact that only one definition is visible at a time, trusting that the compiler/linker do the right thing. I'm not sure we can rely on this.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       I would expect that the object files for client.cc and client_test.cc both contain symbols for FlightClientImpl, and it just so happens that the linker picks the mock when compiling the test binary. 

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       That said, my understanding of this is shaky and maybe there is a good justification for why this works.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Both libarrow_flight_sql.so and client_test.cc.o have symbols for FlightClientImpl for me. That said, they're marked as weak symbols, and presumably the one in the program takes precedence. (Confirmed with LD_DEBUG.)
   
   This works and I'm not going to hold this up, however, it is rather magical and it's worth at least a comment explaining the intent of FlightClientImpl.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Both libarrow_flight_sql.so and client_test.cc.o have symbols for FlightClientImpl for me. That said, they're marked as weak symbols, and presumably the one in the program takes precedence. (Confirmed with LD_DEBUG.)
   
   <details>
   
   ```
   > nm -C src/arrow/flight/flight_sql/CMakeFiles/arrow-flight-sql-client-test.dir/client_test.cc.o | rg FlightClientImpl::DoPut
   0000000000000000 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   > nm -C debug/libarrow_flight_sql.so | rg FlightClientImpl::DoPut
   00000000000f1dc0 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   > nm -C debug/arrow-flight-sql-client-test | rg FlightClientImpl::DoPut
   000000000055b320 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   ```
   
   </details>
   
   This works and I'm not going to hold this up, however, it is rather magical and it's worth at least a comment explaining the intent of FlightClientImpl.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Er, sorry for the churn @rafael-telles but I think the latest commit is strictly worse. I think the situation is OK as-is so long as it's clearly documented (and I can't claim to be a linker expert or C++ standard expert so maybe this is all OK and I don't understand the reason why). I'm mostly just concerned that it's unclear what the intent is.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Perhaps, but even then, I would say that an implementation that requires very carefully linking objects together to be correct is not one we should go with.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       (Sorry - I want to try some alternative approaches but haven't found the time. At this rate it may be Friday before I can get into things…)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r740377479



##########
File path: cpp/src/arrow/flight/flight-sql/server.h
##########
@@ -0,0 +1,493 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <arrow/flight/server.h>
+#include <sqlite3.h>

Review comment:
       No! Sorry for the mistake




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles edited a comment on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles edited a comment on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-956457180


   > Regarding the Protobuf issue: I switched to vcpkg as that appears to be what you use, but I can't replicate still. What OS and compiler are you using?
   
   @lidavidm , yes, I am using vcpkg.
   
   ```
   Linux Mint 20.2, 
   cmake version 3.16.3
   g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
   gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
   ```
   
   Thanks for your help @lidavidm , please let me know if any other info is helpful! Working on the other comments
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742320867



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Both libarrow_flight_sql.so and client_test.cc.o have symbols for FlightClientImpl for me. That said, they're marked as weak symbols, and presumably the one in the program takes precedence. (Confirmed with LD_DEBUG.)
   
   <details>
   
   ```
   > nm -C src/arrow/flight/flight_sql/CMakeFiles/arrow-flight-sql-client-test.dir/client_test.cc.o | rg FlightClientImpl::DoPut
   0000000000000000 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   > nm -C debug/libarrow_flight_sql.so | rg FlightClientImpl::DoPut
   00000000000f1dc0 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   > nm -C debug/arrow-flight-sql-client-test | rg FlightClientImpl::DoPut
   000000000055b320 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   ```
   
   </details>
   
   This works and I'm not going to hold this up, however, it is rather magical and it's worth at least a comment explaining the intent of FlightClientImpl.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r740395586



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,116 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")

Review comment:
       Thanks for fixing this.

##########
File path: cpp/src/arrow/flight/flight_sql/test_app_cli.cc
##########
@@ -0,0 +1,194 @@
+// 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/array/builder_binary.h>
+#include <arrow/array/builder_primitive.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight_sql/api.h>
+#include <arrow/io/memory.h>
+#include <arrow/pretty_print.h>
+#include <arrow/status.h>
+#include <arrow/table.h>
+#include <gflags/gflags.h>
+
+#include <boost/algorithm/string.hpp>
+#include <iostream>
+#include <memory>
+
+using arrow::Result;
+using arrow::Schema;
+using arrow::Status;
+using arrow::flight::ClientAuthHandler;
+using arrow::flight::FlightCallOptions;
+using arrow::flight::FlightClient;
+using arrow::flight::FlightDescriptor;
+using arrow::flight::FlightEndpoint;
+using arrow::flight::FlightInfo;
+using arrow::flight::FlightStreamChunk;
+using arrow::flight::FlightStreamReader;
+using arrow::flight::Location;
+using arrow::flight::Ticket;
+using arrow::flight::sql::FlightSqlClient;
+
+DEFINE_string(host, "localhost", "Host to connect to");
+DEFINE_int32(port, 32010, "Port to connect to");
+DEFINE_string(username, "", "Username");
+DEFINE_string(password, "", "Password");
+
+DEFINE_string(command, "", "Method to run");
+DEFINE_string(query, "", "Query");
+DEFINE_string(catalog, "", "Catalog");
+DEFINE_string(schema, "", "Schema");
+DEFINE_string(table, "", "Table");
+
+Status PrintResultsForEndpoint(FlightSqlClient& client,
+                               const FlightCallOptions& call_options,
+                               const FlightEndpoint& endpoint) {
+  ARROW_ASSIGN_OR_RAISE(auto stream, client.DoGet(call_options, endpoint.ticket));
+
+  const arrow::Result<std::shared_ptr<Schema>>& schema = stream->GetSchema();
+  ARROW_RETURN_NOT_OK(schema);
+
+  std::cout << "Schema:" << std::endl;
+  std::cout << schema->get()->ToString() << std::endl << std::endl;
+
+  std::cout << "Results:" << std::endl;
+
+  FlightStreamChunk chunk;
+  int64_t num_rows = 0;
+
+  while (true) {
+    ARROW_RETURN_NOT_OK(stream->Next(&chunk));
+    if (!(chunk.data != nullptr)) {
+      break;
+    }
+    std::cout << chunk.data->ToString() << std::endl;
+    num_rows += chunk.data->num_rows();
+  }
+
+  std::cout << "Total: " << num_rows << std::endl;
+
+  return Status::OK();
+}
+
+Status PrintResults(FlightSqlClient& client, const FlightCallOptions& call_options,
+                    const std::unique_ptr<FlightInfo>& info) {
+  const std::vector<FlightEndpoint>& endpoints = info->endpoints();
+
+  for (size_t i = 0; i < endpoints.size(); i++) {
+    std::cout << "Results from endpoint " << i + 1 << " of " << endpoints.size()
+              << std::endl;
+    ARROW_RETURN_NOT_OK(PrintResultsForEndpoint(client, call_options, endpoints[i]));
+  }
+
+  return Status::OK();
+}
+
+Status RunMain() {
+  std::unique_ptr<FlightClient> client;
+  Location location;
+  ARROW_RETURN_NOT_OK(Location::ForGrpcTcp(FLAGS_host, FLAGS_port, &location));
+  ARROW_RETURN_NOT_OK(FlightClient::Connect(location, &client));
+
+  FlightCallOptions call_options;
+
+  if (!FLAGS_username.empty() || !FLAGS_password.empty()) {
+    Result<std::pair<std::string, std::string>> bearer_result =
+        client->AuthenticateBasicToken({}, FLAGS_username, FLAGS_password);
+    ARROW_RETURN_NOT_OK(bearer_result);
+
+    call_options.headers.push_back(bearer_result.ValueOrDie());
+  }
+
+  FlightSqlClient sqlClient(std::move(client));

Review comment:
       nit: sql_client




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm edited a comment on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm edited a comment on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-958006483


   Thanks. I'm still digging at this. vcpkg made a change recently that breaks the build, so I need to figure out that first…
   
   (In ARROW-14560)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742376780



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Perhaps, but even then, I would say that an implementation that requires very carefully linking objects together to be correct is not one we should go with.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r738771833



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+               STATIC_LINK_LIBS
+               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+               GTest::gtest
+               GTest::gmock
+               LABELS
+               "arrow_flight_sql")
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
+                                                  ${GFLAGS_LIBRARIES})
+
+find_package(SQLite3)
+include_directories(${SQLite3_INCLUDE_DIRS})
+
+add_executable(flight_sql_test_server
+               server.cc
+               test_server_cli.cc
+               example/sqlite_statement.cc
+               example/sqlite_statement_batch_reader.cc
+               example/sqlite_server.cc
+               example/sqlite_tables_schema_batch_reader.cpp
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
+target_link_libraries(flight_sql_test_server
+                      PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}
+                              ${SQLite3_LIBRARIES})

Review comment:
       I see, we did this for the server tests:
   
   ```
     if(ARROW_BUILD_TESTS)
       add_dependencies(arrow-flight-sql-server-test flight_sql_test_server)
     endif()
   ```
   
   The `flight_sql_test_app` is standalone.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r739235905



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,233 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl;
+}
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+ private:
+  std::shared_ptr<internal::FlightClientImpl> impl_;
+
+ public:
+  class PreparedStatement;
+
+  explicit FlightSqlClient(std::shared_ptr<internal::FlightClientImpl> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query) const;
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query) const;
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options) const;
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern) const;
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket) const;
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types) const;
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table) const;
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table) const;
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options) const;
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(
+      const FlightCallOptions& options, const std::vector<int>& sql_info) const;
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(
+      const FlightCallOptions& options,
+      const std::vector<pb::sql::SqlInfo>& sql_info) const;
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  explicit FlightSqlClient(std::unique_ptr<FlightClient> client);
+
+  class PreparedStatement {
+    std::shared_ptr<internal::FlightClientImpl> client_;
+    FlightCallOptions options_;
+    pb::sql::ActionCreatePreparedStatementResult prepared_statement_result_;
+    std::shared_ptr<RecordBatch> parameter_binding_;
+    bool is_closed_;
+
+   public:
+    /// \brief Constructor for the PreparedStatement class.
+    /// \param[in] query      The query that will be executed.
+    PreparedStatement(

Review comment:
       note that Doxygen complains here since only one of the parameters is documented.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742233667



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       We're defining FlightClientImpl twice and just using the fact that only one definition is visible at a time, trusting that the compiler/linker do the right thing. I'm not sure we can rely on this.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       I would expect that the object files for client.cc and client_test.cc both contain symbols for FlightClientImpl, and it just so happens that the linker picks the mock when compiling the test binary. 

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       That said, my understanding of this is shaky and maybe there is a good justification for why this works.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Both libarrow_flight_sql.so and client_test.cc.o have symbols for FlightClientImpl for me. That said, they're marked as weak symbols, and presumably the one in the program takes precedence. (Confirmed with LD_DEBUG.)
   
   This works and I'm not going to hold this up, however, it is rather magical and it's worth at least a comment explaining the intent of FlightClientImpl.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Both libarrow_flight_sql.so and client_test.cc.o have symbols for FlightClientImpl for me. That said, they're marked as weak symbols, and presumably the one in the program takes precedence. (Confirmed with LD_DEBUG.)
   
   <details>
   
   ```
   > nm -C src/arrow/flight/flight_sql/CMakeFiles/arrow-flight-sql-client-test.dir/client_test.cc.o | rg FlightClientImpl::DoPut
   0000000000000000 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   > nm -C debug/libarrow_flight_sql.so | rg FlightClientImpl::DoPut
   00000000000f1dc0 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   > nm -C debug/arrow-flight-sql-client-test | rg FlightClientImpl::DoPut
   000000000055b320 W arrow::flight::sql::internal::FlightClientImpl::DoPut(arrow::flight::FlightCallOptions const&, arrow::flight::FlightDescriptor const&, std::shared_ptr<arrow::Schema> const&, std::unique_ptr<arrow::flight::FlightStreamWriter, std::default_delete<arrow::flight::FlightStreamWriter> >*, std::unique_ptr<arrow::flight::FlightMetadataReader, std::default_delete<arrow::flight::FlightMetadataReader> >*)
   ```
   
   </details>
   
   This works and I'm not going to hold this up, however, it is rather magical and it's worth at least a comment explaining the intent of FlightClientImpl.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Er, sorry for the churn @rafael-telles but I think the latest commit is strictly worse. I think the situation is OK as-is so long as it's clearly documented (and I can't claim to be a linker expert or C++ standard expert so maybe this is all OK and I don't understand the reason why). I'm mostly just concerned that it's unclear what the intent is.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Perhaps, but even then, I would say that an implementation that requires very carefully linking objects together to be correct is not one we should go with.

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       (Sorry - I want to try some alternative approaches but haven't found the time. At this rate it may be Friday before I can get into things…)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] github-actions[bot] commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
github-actions[bot] commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-948836038


   https://issues.apache.org/jira/browse/ARROW-14421


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-948837995


   @lidavidm , just saw the linter pointed some code style issues, already fixed them


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746831813



##########
File path: cpp/src/arrow/flight/flight_sql/example/sqlite_server.cc
##########
@@ -0,0 +1,676 @@
+// 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/api.h>
+#include <arrow/flight/flight_sql/example/sqlite_server.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement.h>
+#include <arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h>
+#include <arrow/flight/flight_sql/example/sqlite_tables_schema_batch_reader.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <sqlite3.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_io.hpp>
+#include <sstream>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+std::shared_ptr<DataType> GetArrowType(const char* sqlite_type) {
+  if (sqlite_type == NULLPTR) {
+    // SQLite may not know the column type yet.
+    return null();
+  }
+
+  if (boost::iequals(sqlite_type, "int") || boost::iequals(sqlite_type, "integer")) {
+    return int64();
+  } else if (boost::iequals(sqlite_type, "REAL")) {
+    return float64();
+  } else if (boost::iequals(sqlite_type, "BLOB")) {
+    return binary();
+  } else if (boost::iequals(sqlite_type, "TEXT") ||
+             boost::istarts_with(sqlite_type, "char") ||
+             boost::istarts_with(sqlite_type, "varchar")) {
+    return utf8();
+  } else {
+    return null();
+  }
+}
+
+std::string PrepareQueryForGetTables(const GetTables& command) {
+  std::stringstream table_query;
+
+  table_query << "SELECT null as catalog_name, null as schema_name, name as "
+                 "table_name, type as table_type FROM sqlite_master where 1=1";
+
+  if (command.catalog.has_value()) {
+    table_query << " and catalog_name='" << command.catalog.value() << "'";
+  }
+
+  if (command.schema_filter_pattern.has_value()) {
+    table_query << " and schema_name LIKE '" << command.schema_filter_pattern.value()
+                << "'";
+  }
+
+  if (command.table_name_filter_pattern.has_value()) {
+    table_query << " and table_name LIKE '" << command.table_name_filter_pattern.value()
+                << "'";
+  }
+
+  if (!command.table_types.empty()) {
+    table_query << " and table_type IN (";
+    size_t size = command.table_types.size();
+    for (size_t i = 0; i < size; i++) {
+      table_query << "'" << command.table_types[i] << "'";
+      if (size - 1 != i) {
+        table_query << ",";
+      }
+    }
+
+    table_query << ")";
+  }
+
+  table_query << " order by table_name";
+  return table_query.str();
+}
+
+Status SetParametersOnSQLiteStatement(sqlite3_stmt* stmt, FlightMessageReader* reader) {
+  FlightStreamChunk chunk;
+  while (true) {
+    RETURN_NOT_OK(reader->Next(&chunk));
+    std::shared_ptr<RecordBatch>& record_batch = chunk.data;
+    if (record_batch == nullptr) break;
+
+    const int64_t num_rows = record_batch->num_rows();
+    const int& num_columns = record_batch->num_columns();
+
+    for (int i = 0; i < num_rows; ++i) {
+      for (int c = 0; c < num_columns; ++c) {
+        const std::shared_ptr<Array>& column = record_batch->column(c);
+        ARROW_ASSIGN_OR_RAISE(std::shared_ptr<Scalar> scalar, column->GetScalar(i));
+
+        auto& holder = static_cast<DenseUnionScalar&>(*scalar).value;
+
+        switch (holder->type->id()) {
+          case Type::INT64: {
+            int64_t value = static_cast<Int64Scalar&>(*holder).value;
+            sqlite3_bind_int64(stmt, c + 1, value);
+            break;
+          }
+          case Type::FLOAT: {
+            double value = static_cast<FloatScalar&>(*holder).value;
+            sqlite3_bind_double(stmt, c + 1, value);
+            break;
+          }
+          case Type::STRING: {
+            std::shared_ptr<Buffer> buffer = static_cast<StringScalar&>(*holder).value;
+            sqlite3_bind_text(stmt, c + 1, reinterpret_cast<const char*>(buffer->data()),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          case Type::BINARY: {
+            std::shared_ptr<Buffer> buffer = static_cast<BinaryScalar&>(*holder).value;
+            sqlite3_bind_blob(stmt, c + 1, buffer->data(),
+                              static_cast<int>(buffer->size()), SQLITE_TRANSIENT);
+            break;
+          }
+          default:
+            return Status::Invalid("Received unsupported data type: ",
+                                   holder->type->ToString());
+        }
+      }
+    }
+  }
+
+  return Status::OK();
+}
+
+SQLiteFlightSqlServer::SQLiteFlightSqlServer(sqlite3* db) : db_(db), uuid_generator_({}) {
+  assert(db_);
+}
+
+arrow::Result<std::shared_ptr<SQLiteFlightSqlServer>> SQLiteFlightSqlServer::Create() {
+  sqlite3* db = nullptr;
+
+  if (sqlite3_open(":memory:", &db)) {
+    std::string err_msg = "Can't open database: ";
+    if (db != nullptr) {
+      err_msg += sqlite3_errmsg(db);
+      sqlite3_close(db);
+    } else {
+      err_msg += "Unable to start SQLite. Insufficient memory";
+    }
+
+    return Status::RError(err_msg);
+  }
+
+  std::shared_ptr<SQLiteFlightSqlServer> result(new SQLiteFlightSqlServer(db));

Review comment:
       Ah, sorry, this is OK then.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r747033316



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       Yeah - linking tests statically fixes it. Ok, I'm going to continue to dig into this, but I'm thinking the only solution will be to disallow dynamic linking of libarrow_flight if Protobuf and/or gRPC are statically linked.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746871084



##########
File path: cpp/src/arrow/flight/flight_sql/server.cc
##########
@@ -0,0 +1,663 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#include <arrow/api.h>
+#include <arrow/buffer.h>
+#include <arrow/flight/flight_sql/FlightSql.pb.h>
+#include <arrow/flight/flight_sql/server.h>
+#include <google/protobuf/any.pb.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/uuid/uuid.hpp>
+#include <sstream>
+
+#define PROPERTY_TO_OPTIONAL(COMMAND, PROPERTY) \
+  COMMAND.has_##PROPERTY() ? util::make_optional(COMMAND.PROPERTY()) : util::nullopt;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace pb = arrow::flight::protocol;
+
+arrow::Result<GetCrossReference> ParseCommandGetCrossReference(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetCrossReference command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetCrossReference.");
+  }
+
+  GetCrossReference result;
+  result.pk_catalog = PROPERTY_TO_OPTIONAL(command, pk_catalog);
+  result.pk_schema = PROPERTY_TO_OPTIONAL(command, pk_schema);
+  result.pk_table = command.pk_table();
+  result.fk_catalog = PROPERTY_TO_OPTIONAL(command, fk_catalog);
+  result.fk_schema = PROPERTY_TO_OPTIONAL(command, fk_schema);
+  result.fk_table = command.fk_table();
+  return result;
+}
+
+arrow::Result<GetImportedKeys> ParseCommandGetImportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetImportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetImportedKeys.");
+  }
+
+  GetImportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetExportedKeys> ParseCommandGetExportedKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetExportedKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetExportedKeys.");
+  }
+
+  GetExportedKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetPrimaryKeys> ParseCommandGetPrimaryKeys(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandGetPrimaryKeys command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetPrimaryKeys.");
+  }
+
+  GetPrimaryKeys result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema = PROPERTY_TO_OPTIONAL(command, schema);
+  result.table = command.table();
+  return result;
+}
+
+arrow::Result<GetSqlInfo> ParseCommandGetSqlInfo(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSqlInfo command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSqlInfo.");
+  }
+
+  GetSqlInfo result;
+  return result;
+}
+
+arrow::Result<GetSchemas> ParseCommandGetSchemas(const google::protobuf::Any& any) {
+  pb::sql::CommandGetSchemas command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetSchemas.");
+  }
+
+  GetSchemas result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  return result;
+}
+
+arrow::Result<PreparedStatementQuery> ParseCommandPreparedStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementQuery.");
+  }
+
+  PreparedStatementQuery result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<StatementQuery> ParseCommandStatementQuery(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementQuery.");
+  }
+
+  StatementQuery result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<GetTables> ParseCommandGetTables(const google::protobuf::Any& any) {
+  pb::sql::CommandGetTables command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandGetTables.");
+  }
+
+  std::vector<std::string> table_types(command.table_types_size());
+  std::copy(command.table_types().begin(), command.table_types().end(),
+            table_types.begin());
+
+  GetTables result;
+  result.catalog = PROPERTY_TO_OPTIONAL(command, catalog);
+  result.schema_filter_pattern = PROPERTY_TO_OPTIONAL(command, schema_filter_pattern);
+  result.table_name_filter_pattern =
+      PROPERTY_TO_OPTIONAL(command, table_name_filter_pattern);
+  result.table_types = table_types;
+  result.include_schema = command.include_schema();
+  return result;
+}
+
+arrow::Result<StatementQueryTicket> ParseStatementQueryTicket(
+    const google::protobuf::Any& any) {
+  pb::sql::TicketStatementQuery command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack TicketStatementQuery.");
+  }
+
+  StatementQueryTicket result;
+  result.statement_handle = command.statement_handle();
+  return result;
+}
+
+arrow::Result<StatementUpdate> ParseCommandStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandStatementUpdate.");
+  }
+
+  StatementUpdate result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<PreparedStatementUpdate> ParseCommandPreparedStatementUpdate(
+    const google::protobuf::Any& any) {
+  pb::sql::CommandPreparedStatementUpdate command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack CommandPreparedStatementUpdate.");
+  }
+
+  PreparedStatementUpdate result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+arrow::Result<ActionCreatePreparedStatementRequest>
+ParseActionCreatePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionCreatePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionCreatePreparedStatementRequest.");
+  }
+
+  ActionCreatePreparedStatementRequest result;
+  result.query = command.query();
+  return result;
+}
+
+arrow::Result<ActionClosePreparedStatementRequest>
+ParseActionClosePreparedStatementRequest(const google::protobuf::Any& any) {
+  pb::sql::ActionClosePreparedStatementRequest command;
+  if (!any.UnpackTo(&command)) {
+    return Status::Invalid("Unable to unpack ActionClosePreparedStatementRequest.");
+  }
+
+  ActionClosePreparedStatementRequest result;
+  result.prepared_statement_handle = command.prepared_statement_handle();
+  return result;
+}
+
+std::string FlightSqlServerBase::CreateStatementQueryTicket(

Review comment:
       Ah sorry, I missed that. I see now - a free function would make more sense IMO since technically this doesn't need any class state, also this is a generic utility. Can we also document it? 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jcralmeida commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jcralmeida commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746791261



##########
File path: cpp/src/arrow/flight/flight_sql/client.h
##########
@@ -0,0 +1,251 @@
+// 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.
+
+#pragma once
+
+#include <arrow/flight/client.h>
+#include <arrow/flight/types.h>
+#include <arrow/result.h>
+#include <arrow/status.h>
+
+#include <memory>
+#include <string>
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  ~FlightSqlClient();
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.
+  /// \param[in] table_types              The table types to include.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTables(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern, const std::string* table_filter_pattern,
+      bool include_schema, std::vector<std::string>& table_types);
+
+  /// \brief Request the primary keys for a table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The catalog.
+  /// \param[in] schema           The schema.
+  /// \param[in] table            The table.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetPrimaryKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description about the foreign key columns that reference the
+  /// primary key columns of the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The foreign key table catalog.
+  /// \param[in] schema           The foreign key table schema.
+  /// \param[in] table            The foreign key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetExportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves the foreign key columns for the given table.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \param[in] catalog          The primary key table catalog.
+  /// \param[in] schema           The primary key table schema.
+  /// \param[in] table            The primary key table. Cannot be null.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetImportedKeys(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema, const std::string& table);
+
+  /// \brief Retrieves a description of the foreign key columns in the given foreign key
+  ///        table that reference the primary key or the columns representing a unique
+  ///        constraint of the parent table (could be the same or a different table).
+  /// \param[in] options        RPC-layer hints for this call.
+  /// \param[in] pk_catalog     The catalog of the table that exports the key.
+  /// \param[in] pk_schema      The schema of the table that exports the key.
+  /// \param[in] pk_table       The table that exports the key.
+  /// \param[in] fk_catalog     The catalog of the table that imports the key.
+  /// \param[in] fk_schema      The schema of the table that imports the key.
+  /// \param[in] fk_table       The table that imports the key.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCrossReference(
+      const FlightCallOptions& options, const std::string* pk_catalog,
+      const std::string* pk_schema, const std::string& pk_table,
+      const std::string* fk_catalog, const std::string* fk_schema,
+      const std::string& fk_table);
+
+  /// \brief Request a list of table types.
+  /// \param[in] options          RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetTableTypes(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of SQL information.
+  /// \param[in] options RPC-layer hints for this call.
+  /// \param[in] sql_info the SQL info required.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSqlInfo(const FlightCallOptions& options,
+                                                        const std::vector<int>& sql_info);
+
+  /// \brief Create a prepared statement object.
+  /// \param[in] options              RPC-layer hints for this call.
+  /// \param[in] query                The query that will be executed.
+  /// \return The created prepared statement.
+  arrow::Result<std::shared_ptr<PreparedStatement>> Prepare(
+      const FlightCallOptions& options, const std::string& query);
+
+  virtual Status GetFlightInfo(const FlightCallOptions& options,

Review comment:
       Yes, because this function is used by an Anonymous function (GetFlightInfoForCommand).
   




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r749667718



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -87,7 +83,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
 
   add_executable(flight_sql_test_server
                  server.cc
-                 sql_info_util.cc
+                 sql_info_internal.cc

Review comment:
       Hang on. Why are we still linking the library source files into an executable? 

##########
File path: cpp/src/arrow/flight/flight_sql/server.h
##########
@@ -20,24 +20,15 @@
 
 #pragma once
 
-#include <boost/variant.hpp>
 #include <memory>
 #include <string>
 #include <unordered_map>
 
-#include "arrow/flight/flight_sql/example/sqlite_statement.h"
-#include "arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h"
 #include "arrow/flight/flight_sql/server.h"
-#include "arrow/flight/flight_sql/sql_info_util.h"
+#include "arrow/flight/flight_sql/sql_info_internal.h"

Review comment:
       Note that _internal headers will not get installed, so they can't be part of public headers. If we need the typedefs, we should put them in a common header.

##########
File path: cpp/src/arrow/flight/flight_sql/sql_info_internal.h
##########
@@ -20,13 +20,17 @@
 
 #pragma once
 
-#include <boost/variant.hpp>
+#include <arrow/util/variant.h>

Review comment:
       nit - please take care to #include arrow with angle brackets. 

##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -87,7 +83,7 @@ if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
 
   add_executable(flight_sql_test_server
                  server.cc
-                 sql_info_util.cc
+                 sql_info_internal.cc

Review comment:
       Even if the files are marked internal, you should still be able to get at the symbols during linking (you may need to ARROW_EXPORT the classes/functions/etc.)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r757065826



##########
File path: cpp/src/arrow/flight/sql/server.h
##########
@@ -0,0 +1,495 @@
+// 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.
+
+// Interfaces to use for defining Flight RPC servers. API should be considered
+// experimental for now
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+
+#include "arrow/flight/server.h"
+#include "arrow/flight/sql/server.h"
+#include "arrow/flight/sql/sql_info_types.h"
+#include "arrow/util/optional.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+struct StatementQuery {
+  std::string query;
+};
+
+struct StatementUpdate {
+  std::string query;
+};
+
+struct StatementQueryTicket {
+  std::string statement_handle;
+};
+
+struct PreparedStatementQuery {
+  std::string prepared_statement_handle;
+};
+
+struct PreparedStatementUpdate {
+  std::string prepared_statement_handle;
+};
+
+struct GetSqlInfo {
+  std::vector<int32_t> info;
+};
+
+struct GetSchemas {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+};
+
+struct GetTables {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema_filter_pattern;
+  util::optional<std::string> table_name_filter_pattern;
+  std::vector<std::string> table_types;
+  bool include_schema;
+};
+
+struct GetPrimaryKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetExportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetImportedKeys {
+  util::optional<std::string> catalog;
+  util::optional<std::string> schema;
+  std::string table;
+};
+
+struct GetCrossReference {
+  util::optional<std::string> pk_catalog;
+  util::optional<std::string> pk_schema;
+  std::string pk_table;
+  util::optional<std::string> fk_catalog;
+  util::optional<std::string> fk_schema;
+  std::string fk_table;
+};
+
+struct ActionCreatePreparedStatementRequest {
+  std::string query;
+};
+
+struct ActionClosePreparedStatementRequest {
+  std::string prepared_statement_handle;
+};
+
+struct ActionCreatePreparedStatementResult {
+  std::shared_ptr<Schema> dataset_schema;
+  std::shared_ptr<Schema> parameter_schema;
+  std::string prepared_statement_handle;
+};
+
+/// \brief A utility function to create a ticket for a statement query.
+///        Intended for Flight SQL server implementations.
+/// \param[in] statement_handle      The statement handle that will originate the ticket.
+/// \return                          The parsed ticket as an string.
+arrow::Result<std::string> CreateStatementQueryTicket(
+    const std::string& statement_handle);
+
+class ARROW_EXPORT FlightSqlServerBase : public FlightServerBase {
+ private:
+  SqlInfoResultMap sql_info_id_to_result_;
+
+ public:
+  Status GetFlightInfo(const ServerCallContext& context, const FlightDescriptor& request,
+                       std::unique_ptr<FlightInfo>* info) override;
+
+  Status DoGet(const ServerCallContext& context, const Ticket& request,
+               std::unique_ptr<FlightDataStream>* stream) override;
+
+  Status DoPut(const ServerCallContext& context,
+               std::unique_ptr<FlightMessageReader> reader,
+               std::unique_ptr<FlightMetadataWriter> writer) override;
+
+  const ActionType kCreatePreparedStatementActionType =
+      ActionType{"CreatePreparedStatement",
+                 "Creates a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionCreatePreparedStatementRequest\n"
+                 "Response Message: ActionCreatePreparedStatementResult"};
+  const ActionType kClosePreparedStatementActionType =
+      ActionType{"ClosePreparedStatement",
+                 "Closes a reusable prepared statement resource on the server.\n"
+                 "Request Message: ActionClosePreparedStatementRequest\n"
+                 "Response Message: N/A"};
+
+  Status ListActions(const ServerCallContext& context,
+                     std::vector<ActionType>* actions) override;
+
+  Status DoAction(const ServerCallContext& context, const Action& action,
+                  std::unique_ptr<ResultStream>* result) override;
+
+  /// \brief Gets a FlightInfo for executing a SQL query.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQuery object containing the SQL statement.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoStatement(const ServerCallContext& context,
+                                        const StatementQuery& command,
+                                        const FlightDescriptor& descriptor,
+                                        std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The StatementQueryTicket containing the statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetStatement(const ServerCallContext& context,
+                                const StatementQueryTicket& command,
+                                std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for executing an already created prepared statement.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPreparedStatement(const ServerCallContext& context,
+                                                const PreparedStatementQuery& command,
+                                                const FlightDescriptor& descriptor,
+                                                std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the prepared statement query results.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The PreparedStatementQuery object containing the
+  ///                         prepared statement handle.
+  /// \param[out] result      The FlightDataStream containing the results.
+  /// \return                 Status.
+  virtual Status DoGetPreparedStatement(const ServerCallContext& context,
+                                        const PreparedStatementQuery& command,
+                                        std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for listing catalogs.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoCatalogs(const ServerCallContext& context,
+                                       const FlightDescriptor& descriptor,
+                                       std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of catalogs.
+  /// \param[in] context  Per-call context.
+  /// \param[out] result  An interface for sending data back to the client.
+  /// \return             Status.
+  virtual Status DoGetCatalogs(const ServerCallContext& context,
+                               std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for retrieving other information (See SqlInfo).
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetSqlInfo object containing the list of SqlInfo
+  ///                         to be returned.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoSqlInfo(const ServerCallContext& context,
+                                      const GetSqlInfo& command,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of SqlInfo results.
+  /// \param[in] context    Per-call context.
+  /// \param[in] command    The GetSqlInfo object containing the list of SqlInfo
+  ///                       to be returned.
+  /// \param[out] result    The FlightDataStream containing the results.
+  /// \return               Status.
+  virtual Status DoGetSqlInfo(const ServerCallContext& context, const GetSqlInfo& command,
+                              std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo for listing schemas.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetSchemas object which may contain filters for
+  ///                         catalog and schema name.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoSchemas(const ServerCallContext& context,
+                                      const GetSchemas& command,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of schemas.
+  /// \param[in] context   Per-call context.
+  /// \param[in] command   The GetSchemas object which may contain filters for
+  ///                      catalog and schema name.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return              Status.
+  virtual Status DoGetSchemas(const ServerCallContext& context, const GetSchemas& command,
+                              std::unique_ptr<FlightDataStream>* result);
+
+  ///\brief Gets a FlightInfo for listing tables.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetTables object which may contain filters for
+  ///                         catalog, schema and table names.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoTables(const ServerCallContext& context,
+                                     const GetTables& command,
+                                     const FlightDescriptor& descriptor,
+                                     std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the list of tables.
+  /// \param[in] context   Per-call context.
+  /// \param[in] command   The GetTables object which may contain filters for
+  ///                      catalog, schema and table names.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return              Status.
+  virtual Status DoGetTables(const ServerCallContext& context, const GetTables& command,
+                             std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about the table types.
+  /// \param[in] context      Per-call context.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoTableTypes(const ServerCallContext& context,
+                                         const FlightDescriptor& descriptor,
+                                         std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the table types.
+  /// \param[in] context   Per-call context.
+  /// \param[out] result   The FlightDataStream containing the results.
+  /// \return               Status.
+  virtual Status DoGetTableTypes(const ServerCallContext& context,
+                                 std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about primary and foreign keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetPrimaryKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoPrimaryKeys(const ServerCallContext& context,
+                                          const GetPrimaryKeys& command,
+                                          const FlightDescriptor& descriptor,
+                                          std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the primary and
+  /// foreign
+  ///        keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetPrimaryKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetPrimaryKeys(const ServerCallContext& context,
+                                  const GetPrimaryKeys& command,
+                                  std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetExportedKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoExportedKeys(const ServerCallContext& context,
+                                           const GetExportedKeys& command,
+                                           const FlightDescriptor& descriptor,
+                                           std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  /// primary
+  ///        keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetExportedKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetExportedKeys(const ServerCallContext& context,
+                                   const GetExportedKeys& command,
+                                   std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetImportedKeys object with necessary information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoImportedKeys(const ServerCallContext& context,
+                                           const GetImportedKeys& command,
+                                           const FlightDescriptor& descriptor,
+                                           std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  ///        primary keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetImportedKeys object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetImportedKeys(const ServerCallContext& context,
+                                   const GetImportedKeys& command,
+                                   std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Gets a FlightInfo to extract information about foreign and primary keys.
+  /// \param[in] context      Per-call context.
+  /// \param[in] command      The GetCrossReference object with necessary
+  /// information
+  ///                         to execute the request.
+  /// \param[in] descriptor   The descriptor identifying the data stream.
+  /// \param[out] info        The FlightInfo describing where to access the
+  ///                         dataset.
+  /// \return                 Status.
+  virtual Status GetFlightInfoCrossReference(const ServerCallContext& context,
+                                             const GetCrossReference& command,
+                                             const FlightDescriptor& descriptor,
+                                             std::unique_ptr<FlightInfo>* info);
+
+  /// \brief Gets a FlightDataStream containing the data related to the foreign and
+  ///        primary keys.
+  /// \param[in] context  Per-call context.
+  /// \param[in] command  The GetCrossReference object with necessary information
+  ///                     to execute the request.
+  /// \param[out] result  The FlightDataStream containing the results.
+  /// \return             Status.
+  virtual Status DoGetCrossReference(const ServerCallContext& context,
+                                     const GetCrossReference& command,
+                                     std::unique_ptr<FlightDataStream>* result);
+
+  /// \brief Executes an update SQL statement.
+  /// \param[in] context  The call context.
+  /// \param[in] command  The StatementUpdate object containing the SQL statement.
+  /// \param[in] reader   a sequence of uploaded record batches.
+  /// \return             The changed record count.
+  virtual arrow::Result<int64_t> DoPutCommandStatementUpdate(
+      const ServerCallContext& context, const StatementUpdate& command,
+      std::unique_ptr<FlightMessageReader>& reader);
+
+  /// \brief Create a prepared statement from given SQL statement.
+  /// \param[in] context  The call context.
+  /// \param[in] request  The ActionCreatePreparedStatementRequest object containing the
+  ///                     SQL statement.
+  /// \return             A ActionCreatePreparedStatementResult containing the dataset
+  ///                     and parameter schemas and a handle for created statement.
+  virtual arrow::Result<ActionCreatePreparedStatementResult> CreatePreparedStatement(
+      const ServerCallContext& context,
+      const ActionCreatePreparedStatementRequest& request);
+
+  /// \brief Closes a prepared statement.
+  /// \param[in] context  The call context.
+  /// \param[in] request  The ActionClosePreparedStatementRequest object containing the
+  ///                     prepared statement handle.
+  /// \param[out] result  Empty ResultStream.
+  virtual Status ClosePreparedStatement(
+      const ServerCallContext& context,
+      const ActionClosePreparedStatementRequest& request,
+      std::unique_ptr<ResultStream>* result);
+
+  /// \brief Binds parameters to given prepared statement.
+  /// \param[in] context  The call context.
+  /// \param[in] command  The PreparedStatementQuery object containing the
+  ///                     prepared statement handle.
+  /// \param[in] reader   A sequence of uploaded record batches.
+  /// \param[in] writer   Send metadata back to the client.
+  virtual Status DoPutPreparedStatementQuery(const ServerCallContext& context,
+                                             const PreparedStatementQuery& command,
+                                             FlightMessageReader* reader,
+                                             FlightMetadataWriter* writer);
+
+  /// \brief Executes an update SQL prepared statement.
+  /// \param[in] context  The call context.
+  /// \param[in] command  The PreparedStatementUpdate object containing the
+  ///                     prepared statement handle.
+  /// \param[in] reader   a sequence of uploaded record batches.
+  /// \return             The changed record count.
+  virtual arrow::Result<int64_t> DoPutPreparedStatementUpdate(
+      const ServerCallContext& context, const PreparedStatementUpdate& command,
+      FlightMessageReader* reader);
+
+  /// \brief Registers a new SqlInfo result.

Review comment:
       It means that the given SqlInfoResult will be added to the results of GetSqlInfo, clarifying this in this doxygen




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756377299



##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,

Review comment:
       That's because there is a `arrow::flight::Result`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756325763



##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.h
##########
@@ -0,0 +1,87 @@
+// 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.
+
+#pragma once
+
+#include "arrow/flight/sql/sql_info_types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+/// \brief Auxiliary class used to populate GetSqlInfo's DenseUnionArray with different
+/// data types.
+class SqlInfoResultAppender {
+ public:
+  /// \brief Appends a string to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::string& value);
+
+  /// \brief Appends a bool to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(bool value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int64_t value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int32_t value);
+
+  /// \brief Appends a string list to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::vector<std::string>& value);
+
+  /// \brief Appends a int32 to int32 list map to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::unordered_map<int32_t, std::vector<int32_t>>& value);

Review comment:
       It's not the same:
   
   ```c++
   using SqlInfoResult =
       arrow::util::Variant<std::string, bool, int64_t, int32_t, std::vector<std::string>,
                            std::unordered_map<int32_t, std::vector<int32_t>>>;
   using SqlInfoResultMap = std::unordered_map<int32_t, SqlInfoResult>;
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756367840



##########
File path: cpp/src/arrow/flight/sql/client.h
##########
@@ -0,0 +1,259 @@
+// 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.
+
+#pragma once
+
+#include <memory>
+#include <string>
+
+#include "arrow/flight/client.h"
+#include "arrow/flight/types.h"
+#include "arrow/result.h"
+#include "arrow/status.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+class PreparedStatement;
+
+/// \brief Flight client with Flight SQL semantics.
+class ARROW_EXPORT FlightSqlClient {
+  friend class PreparedStatement;
+
+ private:
+  std::shared_ptr<FlightClient> impl_;
+
+ public:
+  explicit FlightSqlClient(std::shared_ptr<FlightClient> client);
+
+  virtual ~FlightSqlClient() = default;
+
+  /// \brief Execute a query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> Execute(const FlightCallOptions& options,
+                                                     const std::string& query);
+
+  /// \brief Execute an update query on the server.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \param[in] query        The query to be executed in the UTF-8 format.
+  /// \return The quantity of rows affected by the operation.
+  arrow::Result<int64_t> ExecuteUpdate(const FlightCallOptions& options,
+                                       const std::string& query);
+
+  /// \brief Request a list of catalogs.
+  /// \param[in] options      RPC-layer hints for this call.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetCatalogs(
+      const FlightCallOptions& options);
+
+  /// \brief Request a list of schemas.
+  /// \param[in] options                RPC-layer hints for this call.
+  /// \param[in] catalog                The catalog.
+  /// \param[in] schema_filter_pattern  The schema filter pattern.
+  /// \return The FlightInfo describing where to access the dataset.
+  arrow::Result<std::unique_ptr<FlightInfo>> GetSchemas(
+      const FlightCallOptions& options, const std::string* catalog,
+      const std::string* schema_filter_pattern);
+
+  /// \brief Given a flight ticket and schema, request to be sent the
+  /// stream. Returns record batch stream reader
+  /// \param[in] options Per-RPC options
+  /// \param[in] ticket The flight ticket to use
+  /// \return The returned RecordBatchReader
+  arrow::Result<std::unique_ptr<FlightStreamReader>> DoGet(
+      const FlightCallOptions& options, const Ticket& ticket);
+
+  /// \brief Request a list of tables.
+  /// \param[in] options                  RPC-layer hints for this call.
+  /// \param[in] catalog                  The catalog.
+  /// \param[in] schema_filter_pattern    The schema filter pattern.
+  /// \param[in] table_filter_pattern     The table filter pattern.
+  /// \param[in] include_schema           True to include the schema upon return,
+  ///                                     false to not include the schema.

Review comment:
       It depends on implementation, where retrieving the columns for each table may require additional work




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r756366604



##########
File path: cpp/src/arrow/flight/sql/sql_info_internal.h
##########
@@ -0,0 +1,87 @@
+// 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.
+
+#pragma once
+
+#include "arrow/flight/sql/sql_info_types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+/// \brief Auxiliary class used to populate GetSqlInfo's DenseUnionArray with different
+/// data types.
+class SqlInfoResultAppender {
+ public:
+  /// \brief Appends a string to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::string& value);
+
+  /// \brief Appends a bool to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(bool value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int64_t value);
+
+  /// \brief Appends a int64_t to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(int32_t value);
+
+  /// \brief Appends a string list to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::vector<std::string>& value);
+
+  /// \brief Appends a int32 to int32 list map to the DenseUnionBuilder.
+  /// \param[in] value Value to be appended.
+  Status operator()(const std::unordered_map<int32_t, std::vector<int32_t>>& value);

Review comment:
       This visitor needs one operator for each type contained on `SqlInfoResult`, so that it can append different data types on DenseUnionArray




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735860428



##########
File path: cpp/src/arrow/flight/flight-sql/server_test.cc
##########
@@ -0,0 +1,653 @@
+// 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/api.h>
+#include <arrow/flight/api.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/flight/flight-sql/example/sqlite_server.h>
+#include <arrow/flight/flight-sql/server.h>
+#include <arrow/flight/test_util.h>
+#include <arrow/flight/types.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#define unparen(...) __VA_ARGS__
+#define DECLARE_ARRAY(ARRAY_NAME, TYPE_CLASS, DATA)     \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME; \
+  {                                                     \
+    arrow::TYPE_CLASS##Builder builder;                 \
+    auto data = unparen DATA;                           \
+    for (const auto& item : data) {                     \
+      ASSERT_OK(builder.Append(item));                  \
+    }                                                   \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));           \
+  }
+
+#define DECLARE_BINARY_ARRAY(ARRAY_NAME, DATA, LENGTH) \
+  std::shared_ptr<arrow::BinaryArray> ARRAY_NAME;      \
+  {                                                    \
+    arrow::Binary##Builder builder;                    \
+    auto data = unparen DATA;                          \
+    for (const auto& item : data) {                    \
+      ASSERT_OK(builder.Append(item, LENGTH));         \
+    }                                                  \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));          \
+  }
+
+#define DECLARE_NULL_ARRAY(ARRAY_NAME, TYPE_CLASS, LENGTH) \
+  std::shared_ptr<arrow::TYPE_CLASS##Array> ARRAY_NAME;    \
+  {                                                        \
+    arrow::TYPE_CLASS##Builder builder;                    \
+    for (int i = 0; i < LENGTH; i++) {                     \
+      ASSERT_OK(builder.AppendNull());                     \
+    }                                                      \
+    ASSERT_OK(builder.Finish(&(ARRAY_NAME)));              \
+  }
+
+using ::testing::_;
+using ::testing::Ref;
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+TestServer* server;
+FlightSqlClient* sql_client;
+
+class TestFlightSqlServer : public ::testing::Environment {
+ protected:
+  void SetUp() override {
+    server = new TestServer("flight_sql_test_server");
+    server->Start();
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    ASSERT_TRUE(server->IsRunning());
+
+    std::stringstream ss;
+    ss << "grpc://localhost:" << server->port();
+    std::string uri = ss.str();
+
+    std::unique_ptr<FlightClient> client;
+    Location location;
+    ASSERT_OK(Location::Parse(uri, &location));
+    ASSERT_OK(FlightClient::Connect(location, &client));
+
+    sql_client = new FlightSqlClient(client);
+  }
+
+  void TearDown() override {
+    server->Stop();
+
+    free(server);
+    free(sql_client);

Review comment:
       Note this causes an AddressSanitizer failure.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-951143181


   Sorry, just a general note: I think we prefer underscores to dashes in the file naming so ideally it would be `cpp/src/arrow/flight/flight_sql` and not `cpp/src/arrow/flight/flight-sql` (there are a few exceptions due to vendored sources).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-952322383


   Hey @lidavidm !
   I applied your diff here and it reproduced the issue when running `server_test.cc`:
   
   ```
   [libprotobuf ERROR /home/rafael/simbiose/vcpkg/buildtrees/protobuf/src/23fa7edd52-3ba2225d30.clean/src/google/protobuf/descriptor.cc:3624] Invalid proto descriptor for file "google/protobuf/descriptor.proto":
   [libprotobuf ERROR /home/rafael/simbiose/vcpkg/buildtrees/protobuf/src/23fa7edd52-3ba2225d30.clean/src/google/protobuf/descriptor.cc:3627]   google/protobuf/descriptor.proto: Unrecognized syntax: SELECT * FROM intTable
   [libprotobuf ERROR /home/rafael/simbiose/vcpkg/buildtrees/protobuf/src/23fa7edd52-3ba2225d30.clean/src/google/protobuf/descriptor.cc:3624] Invalid proto descriptor for file "FlightSql.proto":
   [libprotobuf ERROR /home/rafael/simbiose/vcpkg/buildtrees/protobuf/src/23fa7edd52-3ba2225d30.clean/src/google/protobuf/descriptor.cc:3627]   arrow.flight.protocol.sql.experimental: ".google.protobuf.MessageOptions" is not defined.
   [libprotobuf FATAL /home/rafael/simbiose/vcpkg/buildtrees/protobuf/src/23fa7edd52-3ba2225d30.clean/src/google/protobuf/generated_message_reflection.cc:2457] CHECK failed: file != nullptr: 
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-983006835


   Actually given the latest CI run, it seems the test server isn't starting at all in the AMD64 Conda C++ job. This is one of the Docker-based jobs so you can try to reproduce with`archery docker run conda-cpp` (also see https://arrow.apache.org/docs/developers/docker.html).


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734742855



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       Yes, that was templated to support putting a mock client in for tests.
   
   If I'm reading this right, the suggestion would be to have:
   - client.h methods just be declarations and take in a FlightClientImpl*
   - create a client_internal.h that defines what FlightClientImpl can do.
   - Provide two .cc's that implement FlightClientImpl, one with the logic for a real FlightClient and one for a mock FlightClient. The .cc used will depend on if building for release or for tests.
   - Provide a .cc for FlightSqlClient that invokes the FlightClientImpl.
   
   This should lets us abstract the implementation details for FlightSqlClient while avoiding virtual functions for performance.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r761336106



##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -123,24 +127,35 @@ class SqlInfoDenseUnionValidator {
   SqlInfoDenseUnionValidator& operator=(const SqlInfoDenseUnionValidator&) = delete;
 };
 
-std::unique_ptr<TestServer> server;
-std::unique_ptr<FlightSqlClient> sql_client;
+class TestFlightSqlServer : public ::testing::Test {
+ public:
+  std::unique_ptr<FlightSqlClient> sql_client;
+
+  arrow::Result<int64_t> ExecuteCountQuery(const std::string& query) {
+    ARROW_ASSIGN_OR_RAISE(auto flight_info, sql_client->Execute({}, query));
+
+    ARROW_ASSIGN_OR_RAISE(auto stream,
+                          sql_client->DoGet({}, flight_info->endpoints()[0].ticket));
+
+    std::shared_ptr<Table> table;
+    ARROW_RETURN_NOT_OK(stream->ReadAll(&table));
+
+    const std::shared_ptr<Array>& result_array = table->column(0)->chunk(0);
+    ARROW_ASSIGN_OR_RAISE(auto count_scalar, result_array->GetScalar(0));
+
+    return reinterpret_cast<Int64Scalar&>(*count_scalar).value;
+  }
 
-class TestFlightSqlServer : public ::testing::Environment {
  protected:
   void SetUp() override {
-    server.reset(new TestServer("flight_sql_test_server"));
-    server->Start();
-    for (int i = 0; i < 100; i++) {
-      std::this_thread::sleep_for(std::chrono::milliseconds(10));
-      if (server->IsRunning()) {
-        break;
-      }
-    }
-    ASSERT_TRUE(server->IsRunning());
+    unix_sock = std::tmpnam(nullptr);
+    server_thread.reset(new std::thread(RunServer, this));
+
+    std::unique_lock<std::mutex> lk(server_ready_m);
+    server_ready_cv.wait(lk);
 
     std::stringstream ss;
-    ss << "grpc://localhost:" << server->port();
+    ss << "grpc+unix://" << unix_sock;

Review comment:
       Will this work on Windows? It seems recent versions of 10/11 actually do support domain sockets now, not sure what CI uses, though.

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -153,12 +168,46 @@ class TestFlightSqlServer : public ::testing::Environment {
 
   void TearDown() override {
     sql_client.reset();
-    server->Stop();
-    server.reset();
+
+    ASSERT_OK(server->Shutdown());
+    server_thread->join();
+    server_thread.reset();
+  }
+
+ private:
+  std::string unix_sock;
+  std::shared_ptr<arrow::flight::sql::example::SQLiteFlightSqlServer> server;
+  std::unique_ptr<std::thread> server_thread;
+  std::condition_variable server_ready_cv;
+  std::mutex server_ready_m;
+
+  Status RunServerInternal() {
+    arrow::flight::Location location;
+    ARROW_CHECK_OK(arrow::flight::Location::ForGrpcUnix(unix_sock, &location));
+    arrow::flight::FlightServerOptions options(location);
+
+    ARROW_ASSIGN_OR_RAISE(server,
+                          arrow::flight::sql::example::SQLiteFlightSqlServer::Create())
+
+    ARROW_CHECK_OK(server->Init(options));
+    // Exit with a clean error code (0) on SIGTERM
+    ARROW_CHECK_OK(server->SetShutdownOnSignals({SIGTERM}));
+
+    server_ready_cv.notify_all();
+    ARROW_CHECK_OK(server->Serve());
+
+    return arrow::Status::OK();
+  }
+
+  static void RunServer(TestFlightSqlServer* server) {
+    arrow::Status st = server->RunServerInternal();
+    if (!st.ok()) {
+      std::cerr << st << std::endl;
+    }

Review comment:
       ```suggestion
       ASSERT_OK(server->RunServerInternal());
   ```

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -153,12 +168,46 @@ class TestFlightSqlServer : public ::testing::Environment {
 
   void TearDown() override {
     sql_client.reset();
-    server->Stop();
-    server.reset();
+
+    ASSERT_OK(server->Shutdown());
+    server_thread->join();
+    server_thread.reset();
+  }
+
+ private:
+  std::string unix_sock;
+  std::shared_ptr<arrow::flight::sql::example::SQLiteFlightSqlServer> server;
+  std::unique_ptr<std::thread> server_thread;
+  std::condition_variable server_ready_cv;
+  std::mutex server_ready_m;
+
+  Status RunServerInternal() {
+    arrow::flight::Location location;
+    ARROW_CHECK_OK(arrow::flight::Location::ForGrpcUnix(unix_sock, &location));
+    arrow::flight::FlightServerOptions options(location);
+
+    ARROW_ASSIGN_OR_RAISE(server,
+                          arrow::flight::sql::example::SQLiteFlightSqlServer::Create())
+
+    ARROW_CHECK_OK(server->Init(options));
+    // Exit with a clean error code (0) on SIGTERM
+    ARROW_CHECK_OK(server->SetShutdownOnSignals({SIGTERM}));
+
+    server_ready_cv.notify_all();
+    ARROW_CHECK_OK(server->Serve());
+
+    return arrow::Status::OK();
+  }
+
+  static void RunServer(TestFlightSqlServer* server) {
+    arrow::Status st = server->RunServerInternal();
+    if (!st.ok()) {
+      std::cerr << st << std::endl;
+    }

Review comment:
       Actually, above we're using `ARROW_CHECK_OK` so maybe we can avoid having `RunServer` and `RunServerInternal`.

##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name, then schema_name.
+ */
+message CommandGetSchemas {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, the pattern will not be used to narrow the search.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+}
+
+/*
+ * Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  table_type: utf8 not null,
+ *  [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema,
+ *                                           it is serialized as an IPC message.)
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, then table_type, followed by table_schema if requested.
+ */
+message CommandGetTables {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, all schemas matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+
+  /*
+   * Specifies a filter pattern for tables to search for.
+   * When no table_name_filter_pattern is provided, all tables matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string table_name_filter_pattern = 3;
+
+  // Specifies a filter of table types which must match.

Review comment:
       Just a reminder here @rafael-telles 

##########
File path: cpp/src/arrow/flight/sql/CMakeLists.txt
##########
@@ -66,36 +66,34 @@ else()
                                       ${ARROW_TEST_LINK_LIBS})
 endif()
 
-add_arrow_test(flight_sql_test
-               SOURCES
-               client_test.cc
-               server_test.cc
-               example/sqlite_sql_info.cc
-               STATIC_LINK_LIBS
-               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
-               LABELS
-               "arrow_flight_sql")
-
 # Build test server for unit tests
 if(ARROW_BUILD_TESTS OR ARROW_BUILD_EXAMPLES)
   find_package(SQLite3Alt REQUIRED)
 
-  add_executable(flight_sql_test_server
-                 test_server_cli.cc
-                 example/sqlite_sql_info.cc
-                 example/sqlite_statement.cc
-                 example/sqlite_statement_batch_reader.cc
-                 example/sqlite_server.cc
-                 example/sqlite_tables_schema_batch_reader.cc)
+  set(flight_sql_test_server_SRCS

Review comment:
       Two things:
   
   This should perhaps be something like `ARROW_FLIGHT_SQL_TEST_SERVER_SRCS`, and why does the CLI need anything more than `sqlite_sql_info.cc`?

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -153,12 +168,46 @@ class TestFlightSqlServer : public ::testing::Environment {
 
   void TearDown() override {
     sql_client.reset();
-    server->Stop();
-    server.reset();
+
+    ASSERT_OK(server->Shutdown());
+    server_thread->join();
+    server_thread.reset();
+  }
+
+ private:
+  std::string unix_sock;
+  std::shared_ptr<arrow::flight::sql::example::SQLiteFlightSqlServer> server;
+  std::unique_ptr<std::thread> server_thread;
+  std::condition_variable server_ready_cv;
+  std::mutex server_ready_m;
+
+  Status RunServerInternal() {
+    arrow::flight::Location location;
+    ARROW_CHECK_OK(arrow::flight::Location::ForGrpcUnix(unix_sock, &location));
+    arrow::flight::FlightServerOptions options(location);
+
+    ARROW_ASSIGN_OR_RAISE(server,
+                          arrow::flight::sql::example::SQLiteFlightSqlServer::Create())

Review comment:
       You could do this as `ARROW_CHECK_OK(Create().Value(&server))` and then this wouldn't have to return Status anymore.

##########
File path: cpp/src/arrow/flight/sql/types.h
##########
@@ -0,0 +1,888 @@
+// 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.
+
+#pragma once
+
+#include <unordered_map>
+#include <vector>

Review comment:
       nit: technically we should also #include `<cstdint>` and `<string>` here

##########
File path: cpp/src/arrow/flight/sql/server_test.cc
##########
@@ -153,12 +168,46 @@ class TestFlightSqlServer : public ::testing::Environment {
 
   void TearDown() override {
     sql_client.reset();
-    server->Stop();
-    server.reset();
+
+    ASSERT_OK(server->Shutdown());
+    server_thread->join();
+    server_thread.reset();
+  }
+
+ private:
+  std::string unix_sock;
+  std::shared_ptr<arrow::flight::sql::example::SQLiteFlightSqlServer> server;
+  std::unique_ptr<std::thread> server_thread;
+  std::condition_variable server_ready_cv;
+  std::mutex server_ready_m;
+
+  Status RunServerInternal() {
+    arrow::flight::Location location;
+    ARROW_CHECK_OK(arrow::flight::Location::ForGrpcUnix(unix_sock, &location));
+    arrow::flight::FlightServerOptions options(location);
+
+    ARROW_ASSIGN_OR_RAISE(server,
+                          arrow::flight::sql::example::SQLiteFlightSqlServer::Create())
+
+    ARROW_CHECK_OK(server->Init(options));
+    // Exit with a clean error code (0) on SIGTERM
+    ARROW_CHECK_OK(server->SetShutdownOnSignals({SIGTERM}));
+
+    server_ready_cv.notify_all();
+    ARROW_CHECK_OK(server->Serve());
+
+    return arrow::Status::OK();
+  }
+
+  static void RunServer(TestFlightSqlServer* server) {
+    arrow::Status st = server->RunServerInternal();
+    if (!st.ok()) {
+      std::cerr << st << std::endl;
+    }

Review comment:
       Though ideally it would abort the test if setup fails.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-985798193


   @pitrou @lidavidm - now I think everything was addressed!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r746833221



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       I tried this patch, but it don't solve the ODR violation and tests fail...
   I also noticed that if I just change `builtin-baseline` key on vcpkg.json the tests already fail in the current workaround. Still investigating this




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r747031687



##########
File path: cpp/cmake_modules/FindSQLite3Alt.cmake
##########
@@ -0,0 +1,43 @@
+# 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.
+
+# Once done this will define
+# - FindSQLite3Alt
+#
+# This module will set the following variables if found:
+#  SQLite3_INCLUDE_DIRS  - SQLite3 include dir.
+#  SQLite3_LIBRARIES     - List of libraries when using SQLite3.
+#  SQLite3_FOUND         - True if SQLite3 found.
+#
+# Usage of this module as follows:
+# find_package(SQLite3Alt)
+
+find_path(SQLite3_INCLUDE_DIR sqlite3.h)
+find_library(SQLite3_LIBRARY NAMES sqlite3)
+
+# handle the QUIETLY and REQUIRED arguments and set SQLite3_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(SQLite3Alt FAULT_MSG SQLite3_LIBRARY
+                                  SQLite3_INCLUDE_DIR)
+
+mark_as_advanced(SQLite3_LIBRARY SQLite3_INCLUDE_DIR)
+
+if(SQLite3_FOUND)

Review comment:
       This should be SQLite3Alt_FOUND

##########
File path: cpp/cmake_modules/FindSQLite3Alt.cmake
##########
@@ -0,0 +1,43 @@
+# 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.
+
+# Once done this will define
+# - FindSQLite3Alt
+#
+# This module will set the following variables if found:
+#  SQLite3_INCLUDE_DIRS  - SQLite3 include dir.
+#  SQLite3_LIBRARIES     - List of libraries when using SQLite3.
+#  SQLite3_FOUND         - True if SQLite3 found.
+#
+# Usage of this module as follows:
+# find_package(SQLite3Alt)
+
+find_path(SQLite3_INCLUDE_DIR sqlite3.h)
+find_library(SQLite3_LIBRARY NAMES sqlite3)
+
+# handle the QUIETLY and REQUIRED arguments and set SQLite3_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(SQLite3Alt FAULT_MSG SQLite3_LIBRARY
+                                  SQLite3_INCLUDE_DIR)

Review comment:
       ```suggestion
   find_package_handle_standard_args(SQLite3Alt REQUIRED_VARS SQLite3_LIBRARY
                                     SQLite3_INCLUDE_DIR)
   ```




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r747025192



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       Actually, the first suggestion is probably the only way we can solve things. Presumably what's currently happening is that:
   
   - We have only libprotobuf.a (due to vcpkg),
   - We link it into both libarrow_flight.so and libarrow_flight_sql.so,
   - And we link both into the tests.
   
   Hence we're violating ODR by definition. The only solution is that if we have static protobuf, then we can only build static Flight libraries (since then we won't link libprotobuf.a into libarrow_flight.a, expecting the user to link it themselves).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r747031352



##########
File path: cpp/src/arrow/flight/flight_sql/CMakeLists.txt
##########
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight_sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF})
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS})
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_protobuf_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc client.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight_sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_protobuf_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              STATIC_LINK_LIBS
+              arrow_flight_static)
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_TEST_LINK_LIBS
+      arrow_flight_static arrow_flight_testing_static ${ARROW_FLIGHT_STATIC_LINK_LIBS}
+      ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_TEST_LINK_LIBS arrow_flight_shared arrow_flight_testing_shared
+                                  ${ARROW_TEST_LINK_LIBS})
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)

Review comment:
       Well, now with the latest PR this no longer fails for me…




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r749686255



##########
File path: cpp/src/arrow/flight/flight_sql/server.h
##########
@@ -20,24 +20,15 @@
 
 #pragma once
 
-#include <boost/variant.hpp>
 #include <memory>
 #include <string>
 #include <unordered_map>
 
-#include "arrow/flight/flight_sql/example/sqlite_statement.h"
-#include "arrow/flight/flight_sql/example/sqlite_statement_batch_reader.h"
 #include "arrow/flight/flight_sql/server.h"
-#include "arrow/flight/flight_sql/sql_info_util.h"
+#include "arrow/flight/flight_sql/sql_info_internal.h"

Review comment:
       Fixed by adding a `sql_info_types.h`




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r752434741



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name, then schema_name.
+ */
+message CommandGetSchemas {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, the pattern will not be used to narrow the search.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+}
+
+/*
+ * Represents a request to retrieve the list of tables, and optionally their schemas, on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8,
+ *  table_name: utf8 not null,
+ *  table_type: utf8 not null,
+ *  [optional] table_schema: bytes not null (schema of the table as described in Schema.fbs::Schema,
+ *                                           it is serialized as an IPC message.)
+ * >
+ * The returned data should be ordered by catalog_name, schema_name, table_name, then table_type, followed by table_schema if requested.
+ */
+message CommandGetTables {
+  option (experimental) = true;
+
+  /*
+   * Specifies the Catalog to search for the tables.
+   * An empty string retrieves those without a catalog.
+   * If omitted the catalog name should not be used to narrow the search.
+   */
+  optional string catalog = 1;
+
+  /*
+   * Specifies a filter pattern for schemas to search for.
+   * When no schema_filter_pattern is provided, all schemas matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string schema_filter_pattern = 2;
+
+  /*
+   * Specifies a filter pattern for tables to search for.
+   * When no table_name_filter_pattern is provided, all tables matching other filters are searched.
+   * In the pattern string, two special characters can be used to denote matching rules:
+   *    - "%" means to match any substring with 0 or more characters.
+   *    - "_" means to match any one character.
+   */
+  optional string table_name_filter_pattern = 3;
+
+  // Specifies a filter of table types which must match.

Review comment:
       Table types are usually used to separate tables from views or system tables.
   It's backend specific though there is a common set that most backends support. (TABLE, VIEW, and SYSTEM TABLE are commonly supported, however something like SYNONYM is Oracle-specific). This corresponds to INFORMATION_SCHEMA.TABLES's TABLE_TYPE column.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] jduo commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
jduo commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r752431542



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8 not null
+ * >
+ * The returned data should be ordered by catalog_name.
+ */
+message CommandGetCatalogs {
+  option (experimental) = true;
+}
+
+/*
+ * Represents a request to retrieve the list of schemas on a Flight SQL enabled backend.
+ * Used in the command member of FlightDescriptor for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the catalog metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  catalog_name: utf8,
+ *  schema_name: utf8 not null

Review comment:
       schema is also similar to database. It's a collection of tables.
   Many database systems and DBMS access APIs have a 3-part hierarchy for tables (catalogs hold schemas and schemas hold tables).




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r752427533



##########
File path: format/FlightSql.proto
##########
@@ -0,0 +1,1328 @@
+/*
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+syntax = "proto3";
+import "google/protobuf/descriptor.proto";
+
+option java_package = "org.apache.arrow.flight.sql.impl";
+package arrow.flight.protocol.sql;
+
+/*
+ * Represents a metadata request. Used in the command member of FlightDescriptor
+ * for the following RPC calls:
+ *  - GetSchema: return the schema of the query.
+ *  - GetFlightInfo: execute the metadata request.
+ *
+ * The returned schema will be:
+ * <
+ *  info_name: uint32 not null,
+ *  value: dense_union<
+ *              string_value: utf8,
+ *              bool_value: bool,
+ *              bigint_value: int64,
+ *              int32_bitmask: int32,
+ *              string_list: list<string_data: utf8>
+ *              int32_to_int32_list_map: map<key: int32, value: list<$data$: int32>>
+ * >
+ * where there is one row per requested piece of metadata information.
+ */
+message CommandGetSqlInfo {
+  option (experimental) = true;
+
+  /*
+   * Values are modelled after ODBC's SQLGetInfo() function. This information is intended to provide
+   * Flight SQL clients with basic, SQL syntax and SQL functions related information.
+   * More information types can be added in future releases.
+   * E.g. more SQL syntax support types, scalar functions support, type conversion support etc.
+   *
+   * Note that the set of metadata may expand.
+   *
+   * Initially, Flight SQL will support the following information types:
+   * - Server Information - Range [0-500)
+   * - Syntax Information - Range [500-1000)
+   * Range [0-10,000) is reserved for defaults (see SqlInfo enum for default options). 
+   * Custom options should start at 10,000.
+   *
+   * If omitted, then all metadata will be retrieved.
+   * Flight SQL Servers may choose to include additional metadata above and beyond the specified set, however they must
+   * at least return the specified set. IDs ranging from 0 to 10,000 (exclusive) are reserved for future use.
+   * If additional metadata is included, the metadata IDs should start from 10,000.
+   */
+  repeated uint32 info = 1;
+}
+
+// Options for CommandGetSqlInfo.
+enum SqlInfo {
+
+  // Server Information [0-500): Provides basic information about the Flight SQL Server.
+
+  // Retrieves a UTF-8 string with the name of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_NAME = 0;
+
+  // Retrieves a UTF-8 string with the native version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_VERSION = 1;
+
+  // Retrieves a UTF-8 string with the Arrow format version of the Flight SQL Server.
+  FLIGHT_SQL_SERVER_ARROW_VERSION = 2;
+
+  /* 
+   * Retrieves a boolean value indicating whether the Flight SQL Server is read only.
+   *
+   * Returns:
+   * - false: if read-write
+   * - true: if read only
+   */
+  FLIGHT_SQL_SERVER_READ_ONLY = 3;
+
+
+  // SQL Syntax Information [500-1000): provides information about SQL syntax supported by the Flight SQL Server.
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of catalogs.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of catalogs.
+   * - true: if it supports CREATE and DROP of catalogs.
+   */
+  SQL_DDL_CATALOG = 500;
+
+  /*
+   * Retrieves a boolean value indicating whether the Flight SQL Server supports CREATE and DROP of schemas.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of schemas.
+   * - true: if it supports CREATE and DROP of schemas.
+   */
+  SQL_DDL_SCHEMA = 501;
+
+  /*
+   * Indicates whether the Flight SQL Server supports CREATE and DROP of tables.
+   *
+   * Returns:
+   * - false: if it doesn't support CREATE and DROP of tables.
+   * - true: if it supports CREATE and DROP of tables.
+   */
+  SQL_DDL_TABLE = 502;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of catalog, table and schema names.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_IDENTIFIER_CASE = 503;
+
+  // Retrieves a UTF-8 string with the supported character(s) used to surround a delimited identifier.
+  SQL_IDENTIFIER_QUOTE_CHAR = 504;
+
+  /*
+   * Retrieves a uint32 value representing the enu uint32 ordinal for the case sensitivity of quoted identifiers.
+   *
+   * The possible values are listed in `arrow.flight.protocol.sql.SqlSupportedCaseSensitivity`.
+   */
+  SQL_QUOTED_IDENTIFIER_CASE = 505;
+
+  /*
+   * Retrieves a boolean value indicating whether all tables are selectable.
+   *
+   * Returns:
+   * - false: if not all tables are selectable or if none are;
+   * - true: if all tables are selectable.
+   */
+  SQL_ALL_TABLES_ARE_SELECTABLE = 506;
+
+  /*
+   * Retrieves the null ordering.
+   *
+   * Returns a uint32 ordinal for the null ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlNullOrdering`.
+   */
+  SQL_NULL_ORDERING = 507;
+
+  // Retrieves a UTF-8 string list with values of the supported keywords.
+  SQL_KEYWORDS = 508;
+
+  // Retrieves a UTF-8 string list with values of the supported numeric functions.
+  SQL_NUMERIC_FUNCTIONS = 509;
+
+  // Retrieves a UTF-8 string list with values of the supported string functions.
+  SQL_STRING_FUNCTIONS = 510;
+
+  // Retrieves a UTF-8 string list with values of the supported system functions.
+  SQL_SYSTEM_FUNCTIONS = 511;
+
+  // Retrieves a UTF-8 string list with values of the supported datetime functions.
+  SQL_DATETIME_FUNCTIONS = 512;
+
+  /*
+   * Retrieves the UTF-8 string that can be used to escape wildcard characters.
+   * This is the string that can be used to escape '_' or '%' in the catalog search parameters that are a pattern
+   * (and therefore use one of the wildcard characters).
+   * The '_' character represents any single character; the '%' character represents any sequence of zero or more
+   * characters.
+   */
+  SQL_SEARCH_STRING_ESCAPE = 513;
+
+  /*
+   * Retrieves a UTF-8 string with all the "extra" characters that can be used in unquoted identifier names
+   * (those beyond a-z, A-Z, 0-9 and _).
+   */
+  SQL_EXTRA_NAME_CHARACTERS = 514;
+
+  /*
+   * Retrieves a boolean value indicating whether column aliasing is supported.
+   * If so, the SQL AS clause can be used to provide names for computed columns or to provide alias names for columns
+   * as required.
+   *
+   * Returns:
+   * - false: if column aliasing is unsupported;
+   * - true: if column aliasing is supported.
+   */
+  SQL_SUPPORTS_COLUMN_ALIASING = 515;
+
+  /*
+   * Retrieves a boolean value indicating whether concatenations between null and non-null values being
+   * null are supported.
+   *
+   * - Returns:
+   * - false: if concatenations between null and non-null values being null are unsupported;
+   * - true: if concatenations between null and non-null values being null are supported.
+   */
+  SQL_NULL_PLUS_NULL_IS_NULL = 516;
+
+  /*
+   * Retrieves a map where the key is the type to convert from and the value is a list with the types to convert to,
+   * indicating the supported conversions. Each key and each item on the list value is a value to a predefined type on
+   * SqlSupportsConvert enum.
+   * The returned map will be:  map<int32, list<int32>>
+   */
+  SQL_SUPPORTS_CONVERT = 517;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if table correlation names are unsupported;
+   * - true: if table correlation names are supported.
+   */
+  SQL_SUPPORTS_TABLE_CORRELATION_NAMES = 518;
+
+  /*
+   * Retrieves a boolean value indicating whether, when table correlation names are supported,
+   * they are restricted to being different from the names of the tables.
+   *
+   * Returns:
+   * - false: if different table correlation names are unsupported;
+   * - true: if different table correlation names are supported
+   */
+  SQL_SUPPORTS_DIFFERENT_TABLE_CORRELATION_NAMES = 519;
+
+  /*
+   * Retrieves a boolean value indicating whether expressions in ORDER BY lists are supported.
+   *
+   * Returns:
+   * - false: if expressions in ORDER BY are unsupported;
+   * - true: if expressions in ORDER BY are supported;
+   */
+  SQL_SUPPORTS_EXPRESSIONS_IN_ORDER_BY = 520;
+
+  /*
+   * Retrieves a boolean value indicating whether using a column that is not in the SELECT statement in a GROUP BY
+   * clause is supported.
+   *
+   * Returns:
+   * - false: if using a column that is not in the SELECT statement in a GROUP BY clause is unsupported;
+   * - true: if using a column that is not in the SELECT statement in a GROUP BY clause is supported.
+   */
+  SQL_SUPPORTS_ORDER_BY_UNRELATED = 521;
+
+  /*
+   * Retrieves the supported GROUP BY commands;
+   *
+   * Returns an int32 bitmask value representing the supported commands.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (GROUP BY is unsupported);
+   * - return 1 (\b1)   => [SQL_GROUP_BY_UNRELATED];
+   * - return 2 (\b10)  => [SQL_GROUP_BY_BEYOND_SELECT];
+   * - return 3 (\b11)  => [SQL_GROUP_BY_UNRELATED, SQL_GROUP_BY_BEYOND_SELECT].
+   * Valid GROUP BY types are described under `arrow.flight.protocol.sql.SqlSupportedGroupBy`.
+   */
+  SQL_SUPPORTED_GROUP_BY = 522;
+
+  /*
+   * Retrieves a boolean value indicating whether specifying a LIKE escape clause is supported.
+   *
+   * Returns:
+   * - false: if specifying a LIKE escape clause is unsupported;
+   * - true: if specifying a LIKE escape clause is supported.
+   */
+  SQL_SUPPORTS_LIKE_ESCAPE_CLAUSE = 523;
+
+  /*
+   * Retrieves a boolean value indicating whether columns may be defined as non-nullable.
+   *
+   * Returns:
+   * - false: if columns cannot be defined as non-nullable;
+   * - true: if columns may be defined as non-nullable.
+   */
+  SQL_SUPPORTS_NON_NULLABLE_COLUMNS = 524;
+
+  /*
+   * Retrieves the supported SQL grammar level as per the ODBC specification.
+   *
+   * Returns an int32 bitmask value representing the supported SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported grammar levels.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (SQL grammar is unsupported);
+   * - return 1 (\b1)   => [SQL_MINIMUM_GRAMMAR];
+   * - return 2 (\b10)  => [SQL_CORE_GRAMMAR];
+   * - return 3 (\b11)  => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR];
+   * - return 4 (\b100) => [SQL_EXTENDED_GRAMMAR];
+   * - return 5 (\b101) => [SQL_MINIMUM_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 6 (\b110) => [SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR];
+   * - return 7 (\b111) => [SQL_MINIMUM_GRAMMAR, SQL_CORE_GRAMMAR, SQL_EXTENDED_GRAMMAR].
+   * Valid SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedSqlGrammar`.
+   */
+  SQL_SUPPORTED_GRAMMAR = 525;
+
+  /*
+   * Retrieves the supported ANSI92 SQL grammar level.
+   *
+   * Returns an int32 bitmask value representing the supported ANSI92 SQL grammar level.
+   * The returned bitmask should be parsed in order to retrieve the supported commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (ANSI92 SQL grammar is unsupported);
+   * - return 1 (\b1)   => [ANSI92_ENTRY_SQL];
+   * - return 2 (\b10)  => [ANSI92_INTERMEDIATE_SQL];
+   * - return 3 (\b11)  => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL];
+   * - return 4 (\b100) => [ANSI92_FULL_SQL];
+   * - return 5 (\b101) => [ANSI92_ENTRY_SQL, ANSI92_FULL_SQL];
+   * - return 6 (\b110) => [ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL];
+   * - return 7 (\b111) => [ANSI92_ENTRY_SQL, ANSI92_INTERMEDIATE_SQL, ANSI92_FULL_SQL].
+   * Valid ANSI92 SQL grammar levels are described under `arrow.flight.protocol.sql.SupportedAnsi92SqlGrammarLevel`.
+   */
+  SQL_ANSI92_SUPPORTED_LEVEL = 526;
+
+  /*
+   * Retrieves a boolean value indicating whether the SQL Integrity Enhancement Facility is supported.
+   *
+   * Returns:
+   * - false: if the SQL Integrity Enhancement Facility is supported;
+   * - true: if the SQL Integrity Enhancement Facility is supported.
+   */
+  SQL_SUPPORTS_INTEGRITY_ENHANCEMENT_FACILITY = 527;
+
+  /*
+   * Retrieves the support level for SQL OUTER JOINs.
+   *
+   * Returns a uint3 uint32 ordinal for the SQL ordering being used, as described in
+   * `arrow.flight.protocol.sql.SqlOuterJoinsSupportLevel`.
+   */
+  SQL_OUTER_JOINS_SUPPORT_LEVEL = 528;
+
+  // Retrieves a UTF-8 string with the preferred term for "schema".
+  SQL_SCHEMA_TERM = 529;
+
+  // Retrieves a UTF-8 string with the preferred term for "procedure".
+  SQL_PROCEDURE_TERM = 530;
+
+  // Retrieves a UTF-8 string with the preferred term for "catalog".
+  SQL_CATALOG_TERM = 531;
+
+  /*
+   * Retrieves a boolean value indicating whether a catalog appears at the start of a fully qualified table name.
+   *
+   * - false: if a catalog does not appear at the start of a fully qualified table name;
+   * - true: if a catalog appears at the start of a fully qualified table name.
+   */
+  SQL_CATALOG_AT_START = 532;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL schema.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL schema.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL schema);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL schema described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_SCHEMAS_SUPPORTED_ACTIONS = 533;
+
+  /*
+   * Retrieves the supported actions for a SQL schema.
+   *
+   * Returns an int32 bitmask value representing the supported actions for a SQL catalog.
+   * The returned bitmask should be parsed in order to retrieve the supported actions for a SQL catalog.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported actions for SQL catalog);
+   * - return 1 (\b1)   => [SQL_ELEMENT_IN_PROCEDURE_CALLS];
+   * - return 2 (\b10)  => [SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 3 (\b11)  => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS];
+   * - return 4 (\b100) => [SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 5 (\b101) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 6 (\b110) => [SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS];
+   * - return 7 (\b111) => [SQL_ELEMENT_IN_PROCEDURE_CALLS, SQL_ELEMENT_IN_INDEX_DEFINITIONS, SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS].
+   * Valid actions for a SQL catalog are described under `arrow.flight.protocol.sql.SqlSupportedElementActions`.
+   */
+  SQL_CATALOGS_SUPPORTED_ACTIONS = 534;
+
+  /*
+   * Retrieves the supported SQL positioned commands.
+   *
+   * Returns an int32 bitmask value representing the supported SQL positioned commands.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL positioned commands.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_POSITIONED_DELETE];
+   * - return 2 (\b10)  => [SQL_POSITIONED_UPDATE];
+   * - return 3 (\b11)  => [SQL_POSITIONED_DELETE, SQL_POSITIONED_UPDATE].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedPositionedCommands`.
+   */
+  SQL_SUPPORTED_POSITIONED_COMMANDS = 535;
+
+  /*
+   * Retrieves a boolean value indicating whether SELECT FOR UPDATE statements are supported.
+   *
+   * Returns:
+   * - false: if SELECT FOR UPDATE statements are unsupported;
+   * - true: if SELECT FOR UPDATE statements are supported.
+   */
+  SQL_SELECT_FOR_UPDATE_SUPPORTED = 536;
+
+  /*
+   * Retrieves a boolean value indicating whether stored procedure calls that use the stored procedure escape syntax
+   * are supported.
+   *
+   * Returns:
+   * - false: if stored procedure calls that use the stored procedure escape syntax are unsupported;
+   * - true: if stored procedure calls that use the stored procedure escape syntax are supported.
+   */
+  SQL_STORED_PROCEDURES_SUPPORTED = 537;
+
+  /*
+   * Retrieves the supported SQL subqueries.
+   *
+   * Returns an int32 bitmask value representing the supported SQL subqueries.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL subqueries.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL subqueries);
+   * - return 1   (\b1)     => [SQL_SUBQUERIES_IN_COMPARISONS];
+   * - return 2   (\b10)    => [SQL_SUBQUERIES_IN_EXISTS];
+   * - return 3   (\b11)    => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 4   (\b100)   => [SQL_SUBQUERIES_IN_INS];
+   * - return 5   (\b101)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS];
+   * - return 6   (\b110)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS];
+   * - return 7   (\b111)   => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS];
+   * - return 8   (\b1000)  => [SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 9   (\b1001)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 10  (\b1010)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 11  (\b1011)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 12  (\b1100)  => [SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 13  (\b1101)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 14  (\b1110)  => [SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - return 15  (\b1111)  => [SQL_SUBQUERIES_IN_COMPARISONS, SQL_SUBQUERIES_IN_EXISTS, SQL_SUBQUERIES_IN_INS, SQL_SUBQUERIES_IN_QUANTIFIEDS];
+   * - ...
+   * Valid SQL subqueries are described under `arrow.flight.protocol.sql.SqlSupportedSubqueries`.
+   */
+  SQL_SUPPORTED_SUBQUERIES = 538;
+
+  /*
+   * Retrieves a boolean value indicating whether correlated subqueries are supported.
+   *
+   * Returns:
+   * - false: if correlated subqueries are unsupported;
+   * - true: if correlated subqueries are supported.
+   */
+  SQL_CORRELATED_SUBQUERIES_SUPPORTED = 539;
+
+  /*
+   * Retrieves the supported SQL UNIONs.
+   *
+   * Returns an int32 bitmask value representing the supported SQL UNIONs.
+   * The returned bitmask should be parsed in order to retrieve the supported SQL UNIONs.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported SQL positioned commands);
+   * - return 1 (\b1)   => [SQL_UNION];
+   * - return 2 (\b10)  => [SQL_UNION_ALL];
+   * - return 3 (\b11)  => [SQL_UNION, SQL_UNION_ALL].
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlSupportedUnions`.
+   */
+  SQL_SUPPORTED_UNIONS = 540;
+
+  // Retrieves a uint32 value representing the maximum number of hex characters allowed in an inline binary literal.
+  SQL_MAX_BINARY_LITERAL_LENGTH = 541;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a character literal.
+  SQL_MAX_CHAR_LITERAL_LENGTH = 542;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed for a column name.
+  SQL_MAX_COLUMN_NAME_LENGTH = 543;
+
+  // Retrieves a uint32 value representing the the maximum number of columns allowed in a GROUP BY clause.
+  SQL_MAX_COLUMNS_IN_GROUP_BY = 544;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an index.
+  SQL_MAX_COLUMNS_IN_INDEX = 545;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in an ORDER BY clause.
+  SQL_MAX_COLUMNS_IN_ORDER_BY = 546;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a SELECT list.
+  SQL_MAX_COLUMNS_IN_SELECT = 547;
+
+  // Retrieves a uint32 value representing the maximum number of columns allowed in a table.
+  SQL_MAX_COLUMNS_IN_TABLE = 548;
+
+  // Retrieves a uint32 value representing the maximum number of concurrent connections possible.
+  SQL_MAX_CONNECTIONS = 549;
+
+  // Retrieves a uint32 value the maximum number of characters allowed in a cursor name.
+  SQL_MAX_CURSOR_NAME_LENGTH = 550;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of bytes allowed for an index,
+   * including all of the parts of the index.
+   */
+  SQL_MAX_INDEX_LENGTH = 551;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a procedure name.
+  SQL_SCHEMA_NAME_LENGTH = 552;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_PROCEDURE_NAME_LENGTH = 553;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a catalog name.
+  SQL_MAX_CATALOG_NAME_LENGTH = 554;
+
+  // Retrieves a uint32 value representing the maximum number of bytes allowed in a single row.
+  SQL_MAX_ROW_SIZE = 555;
+
+  /*
+   * Retrieves a boolean indicating whether the return value for the JDBC method getMaxRowSize includes the SQL
+   * data types LONGVARCHAR and LONGVARBINARY.
+   *
+   * Returns:
+   * - false: if return value for the JDBC method getMaxRowSize does
+   *          not include the SQL data types LONGVARCHAR and LONGVARBINARY;
+   * - true: if return value for the JDBC method getMaxRowSize includes
+   *         the SQL data types LONGVARCHAR and LONGVARBINARY.
+   */
+  SQL_MAX_ROW_SIZE_INCLUDES_BLOBS = 556;
+
+  /*
+   * Retrieves a uint32 value representing the maximum number of characters allowed for an SQL statement;
+   * a result of 0 (zero) means that there is no limit or the limit is not known.
+   */
+  SQL_MAX_STATEMENT_LENGTH = 557;
+
+  // Retrieves a uint32 value representing the maximum number of active statements that can be open at the same time.
+  SQL_MAX_STATEMENTS = 558;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a table name.
+  SQL_MAX_TABLE_NAME_LENGTH = 559;
+
+  // Retrieves a uint32 value representing the maximum number of tables allowed in a SELECT statement.
+  SQL_MAX_TABLES_IN_SELECT = 560;
+
+  // Retrieves a uint32 value representing the maximum number of characters allowed in a user name.
+  SQL_MAX_USERNAME_LENGTH = 561;
+
+  /*
+   * Retrieves this database's default transaction isolation level as described in
+   * `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   *
+   * Returns a uint32 ordinal for the SQL transaction isolation level.
+   */
+  SQL_DEFAULT_TRANSACTION_ISOLATION = 562;
+
+  /*
+   * Retrieves a boolean value indicating whether transactions are supported. If not, invoking the method commit is a
+   * noop, and the isolation level is `arrow.flight.protocol.sql.SqlTransactionIsolationLevel.TRANSACTION_NONE`.
+   *
+   * Returns:
+   * - false: if transactions are unsupported;
+   * - true: if transactions are supported.
+   */
+  SQL_TRANSACTIONS_SUPPORTED = 563;
+
+  /*
+   * Retrieves the supported transactions isolation levels.
+   *
+   * Returns an int32 bitmask value representing the supported transactions isolation levels.
+   * The returned bitmask should be parsed in order to retrieve the supported transactions isolation levels.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported SQL transactions isolation levels);
+   * - return 1   (\b1)     => [SQL_TRANSACTION_NONE];
+   * - return 2   (\b10)    => [SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 3   (\b11)    => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED];
+   * - return 4   (\b100)   => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 5   (\b101)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 6   (\b110)   => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 7   (\b111)   => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 8   (\b1000)  => [SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 9   (\b1001)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 10  (\b1010)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 11  (\b1011)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 12  (\b1100)  => [SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 13  (\b1101)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 14  (\b1110)  => [SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 15  (\b1111)  => [SQL_TRANSACTION_NONE, SQL_TRANSACTION_READ_UNCOMMITTED, SQL_TRANSACTION_REPEATABLE_READ, SQL_TRANSACTION_REPEATABLE_READ];
+   * - return 16  (\b10000) => [SQL_TRANSACTION_SERIALIZABLE];
+   * - ...
+   * Valid SQL positioned commands are described under `arrow.flight.protocol.sql.SqlTransactionIsolationLevel`.
+   */
+  SQL_SUPPORTED_TRANSACTIONS_ISOLATION_LEVELS = 564;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction forces
+   * the transaction to commit.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction does not force the transaction to commit;
+   * - true: if a data definition statement within a transaction forces the transaction to commit.
+   */
+  SQL_DATA_DEFINITION_CAUSES_TRANSACTION_COMMIT = 565;
+
+  /*
+   * Retrieves a boolean value indicating whether a data definition statement within a transaction is ignored.
+   *
+   * Returns:
+   * - false: if a data definition statement within a transaction is taken into account;
+   * - true: a data definition statement within a transaction is ignored.
+   */
+  SQL_DATA_DEFINITIONS_IN_TRANSACTIONS_IGNORED = 566;
+
+  /*
+   * Retrieves an int32 bitmask value representing the supported result set types.
+   * The returned bitmask should be parsed in order to retrieve the supported result set types.
+   *
+   * For instance:
+   * - return 0   (\b0)     => [] (no supported result set types);
+   * - return 1   (\b1)     => [SQL_RESULT_SET_TYPE_UNSPECIFIED];
+   * - return 2   (\b10)    => [SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 3   (\b11)    => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY];
+   * - return 4   (\b100)   => [SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 5   (\b101)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 6   (\b110)   => [SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 7   (\b111)   => [SQL_RESULT_SET_TYPE_UNSPECIFIED, SQL_RESULT_SET_TYPE_FORWARD_ONLY, SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE];
+   * - return 8   (\b1000)  => [SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE];
+   * - ...
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetType`.
+   */
+  SQL_SUPPORTED_RESULT_SET_TYPES = 567;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_UNSPECIFIED`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_UNSPECIFIED = 568;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_FORWARD_ONLY`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_FORWARD_ONLY = 569;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_SENSITIVE = 570;
+
+  /*
+   * Returns an int32 bitmask value concurrency types supported for
+   * `arrow.flight.protocol.sql.SqlSupportedResultSetType.SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE`.
+   *
+   * For instance:
+   * - return 0 (\b0)   => [] (no supported concurrency types for this result set type)
+   * - return 1 (\b1)   => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED]
+   * - return 2 (\b10)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 3 (\b11)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY]
+   * - return 4 (\b100) => [SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 5 (\b101) => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 6 (\b110)  => [SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * - return 7 (\b111)  => [SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED, SQL_RESULT_SET_CONCURRENCY_READ_ONLY, SQL_RESULT_SET_CONCURRENCY_UPDATABLE]
+   * Valid result set types are described under `arrow.flight.protocol.sql.SqlSupportedResultSetConcurrency`.
+   */
+  SQL_SUPPORTED_CONCURRENCIES_FOR_RESULT_SET_SCROLL_INSENSITIVE = 571;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports batch updates.
+   *
+   * - false: if this database does not support batch updates;
+   * - true: if this database supports batch updates.
+   */
+  SQL_BATCH_UPDATES_SUPPORTED = 572;
+
+  /*
+   * Retrieves a boolean value indicating whether this database supports savepoints.
+   *
+   * Returns:
+   * - false: if this database does not support savepoints;
+   * - true: if this database supports savepoints.
+   */
+  SQL_SAVEPOINTS_SUPPORTED = 573;
+
+  /*
+   * Retrieves a boolean value indicating whether named parameters are supported in callable statements.
+   *
+   * Returns:
+   * - false: if named parameters in callable statements are unsupported;
+   * - true: if named parameters in callable statements are supported.
+   */
+  SQL_NAMED_PARAMETERS_SUPPORTED = 574;
+
+  /*
+   * Retrieves a boolean value indicating whether updates made to a LOB are made on a copy or directly to the LOB.
+   *
+   * Returns:
+   * - false: if updates made to a LOB are made directly to the LOB;
+   * - true: if updates made to a LOB are made on a copy.
+   */
+  SQL_LOCATORS_UPDATE_COPY = 575;
+
+  /*
+   * Retrieves a boolean value indicating whether invoking user-defined or vendor functions
+   * using the stored procedure escape syntax is supported.
+   *
+   * Returns:
+   * - false: if invoking user-defined or vendor functions using the stored procedure escape syntax is unsupported;
+   * - true: if invoking user-defined or vendor functions using the stored procedure escape syntax is supported.
+   */
+  SQL_STORED_FUNCTIONS_USING_CALL_SYNTAX_SUPPORTED = 576;
+}
+
+enum SqlSupportedCaseSensitivity {
+  SQL_CASE_SENSITIVITY_UNKNOWN = 0;
+  SQL_CASE_SENSITIVITY_CASE_INSENSITIVE = 1;
+  SQL_CASE_SENSITIVITY_UPPERCASE = 2;
+  SQL_CASE_SENSITIVITY_LOWERCASE = 3;
+}
+
+enum SqlNullOrdering {
+  SQL_NULLS_SORTED_HIGH = 0;
+  SQL_NULLS_SORTED_LOW = 1;
+  SQL_NULLS_SORTED_AT_START = 2;
+  SQL_NULLS_SORTED_AT_END = 3;
+}
+
+enum SupportedSqlGrammar {
+  SQL_MINIMUM_GRAMMAR = 0;
+  SQL_CORE_GRAMMAR = 1;
+  SQL_EXTENDED_GRAMMAR = 2;
+}
+
+enum SupportedAnsi92SqlGrammarLevel {
+  ANSI92_ENTRY_SQL = 0;
+  ANSI92_INTERMEDIATE_SQL = 1;
+  ANSI92_FULL_SQL = 2;
+}
+
+enum SqlOuterJoinsSupportLevel {
+  SQL_JOINS_UNSUPPORTED = 0;
+  SQL_LIMITED_OUTER_JOINS = 1;
+  SQL_FULL_OUTER_JOINS = 2;
+}
+
+enum SqlSupportedGroupBy {
+  SQL_GROUP_BY_UNRELATED = 0;
+  SQL_GROUP_BY_BEYOND_SELECT = 1;
+}
+
+enum SqlSupportedElementActions {
+  SQL_ELEMENT_IN_PROCEDURE_CALLS = 0;
+  SQL_ELEMENT_IN_INDEX_DEFINITIONS = 1;
+  SQL_ELEMENT_IN_PRIVILEGE_DEFINITIONS = 2;
+}
+
+enum SqlSupportedPositionedCommands {
+  SQL_POSITIONED_DELETE = 0;
+  SQL_POSITIONED_UPDATE = 1;
+}
+
+enum SqlSupportedSubqueries {
+  SQL_SUBQUERIES_IN_COMPARISONS = 0;
+  SQL_SUBQUERIES_IN_EXISTS = 1;
+  SQL_SUBQUERIES_IN_INS = 2;
+  SQL_SUBQUERIES_IN_QUANTIFIEDS = 3;
+}
+
+enum SqlSupportedUnions {
+  SQL_UNION = 0;
+  SQL_UNION_ALL = 1;
+}
+
+enum SqlTransactionIsolationLevel {
+  SQL_TRANSACTION_NONE = 0;
+  SQL_TRANSACTION_READ_UNCOMMITTED = 1;
+  SQL_TRANSACTION_READ_COMMITTED = 2;
+  SQL_TRANSACTION_REPEATABLE_READ = 3;
+  SQL_TRANSACTION_SERIALIZABLE = 4;
+}
+
+enum SqlSupportedTransactions {
+  SQL_TRANSACTION_UNSPECIFIED = 0;
+  SQL_DATA_DEFINITION_TRANSACTIONS = 1;
+  SQL_DATA_MANIPULATION_TRANSACTIONS = 2;
+}
+
+enum SqlSupportedResultSetType {
+  SQL_RESULT_SET_TYPE_UNSPECIFIED = 0;
+  SQL_RESULT_SET_TYPE_FORWARD_ONLY = 1;
+  SQL_RESULT_SET_TYPE_SCROLL_INSENSITIVE = 2;
+  SQL_RESULT_SET_TYPE_SCROLL_SENSITIVE = 3;
+}
+
+enum SqlSupportedResultSetConcurrency {
+  SQL_RESULT_SET_CONCURRENCY_UNSPECIFIED = 0;
+  SQL_RESULT_SET_CONCURRENCY_READ_ONLY = 1;
+  SQL_RESULT_SET_CONCURRENCY_UPDATABLE = 2;
+}
+
+enum SqlSupportsConvert {
+  SQL_CONVERT_BIGINT = 0;
+  SQL_CONVERT_BINARY = 1;
+  SQL_CONVERT_BIT = 2;
+  SQL_CONVERT_CHAR = 3;
+  SQL_CONVERT_DATE = 4;
+  SQL_CONVERT_DECIMAL = 5;
+  SQL_CONVERT_FLOAT = 6;
+  SQL_CONVERT_INTEGER = 7;
+  SQL_CONVERT_INTERVAL_DAY_TIME = 8;
+  SQL_CONVERT_INTERVAL_YEAR_MONTH = 9;
+  SQL_CONVERT_LONGVARBINARY = 10;
+  SQL_CONVERT_LONGVARCHAR = 11;
+  SQL_CONVERT_NUMERIC = 12;
+  SQL_CONVERT_REAL = 13;
+  SQL_CONVERT_SMALLINT = 14;
+  SQL_CONVERT_TIME = 15;
+  SQL_CONVERT_TIMESTAMP = 16;
+  SQL_CONVERT_TINYINT = 17;
+  SQL_CONVERT_VARBINARY = 18;
+  SQL_CONVERT_VARCHAR = 19;
+}
+
+/*
+ * Represents a request to retrieve the list of catalogs on a Flight SQL enabled backend.

Review comment:
       It depends on vendor/implementation, but a "catalog" is usually synonymous to "database"




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r763113423



##########
File path: cpp/src/arrow/flight/sql/example/sqlite_sql_info.cc
##########
@@ -0,0 +1,223 @@
+// 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/example/sqlite_sql_info.h"
+
+#include "arrow/flight/sql/types.h"
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace example {
+
+/// \brief Gets the mapping from SQL info ids to SqlInfoResult instances.
+/// \return the cache.
+SqlInfoResultMap GetSqlInfoResultMap() {
+  return {
+      {SqlInfoOptions::SqlInfo::FLIGHT_SQL_SERVER_NAME,
+       SqlInfoResult(std::string("db_name"))},
+      {SqlInfoOptions::SqlInfo::FLIGHT_SQL_SERVER_VERSION,
+       SqlInfoResult(std::string("sqlite 3"))},
+      {SqlInfoOptions::SqlInfo::FLIGHT_SQL_SERVER_ARROW_VERSION,
+       SqlInfoResult(std::string("7.0.0-SNAPSHOT" /* Only an example */))},
+      {SqlInfoOptions::SqlInfo::FLIGHT_SQL_SERVER_READ_ONLY, SqlInfoResult(false)},
+      {SqlInfoOptions::SqlInfo::SQL_DDL_CATALOG,
+       SqlInfoResult(false /* SQLite 3 does not support catalogs */)},
+      {SqlInfoOptions::SqlInfo::SQL_DDL_SCHEMA,
+       SqlInfoResult(false /* SQLite 3 does not support schemas */)},
+      {SqlInfoOptions::SqlInfo::SQL_DDL_TABLE, SqlInfoResult(true)},
+      {SqlInfoOptions::SqlInfo::SQL_IDENTIFIER_CASE,
+       SqlInfoResult(int64_t(SqlInfoOptions::SqlSupportedCaseSensitivity::
+                                 SQL_CASE_SENSITIVITY_CASE_INSENSITIVE))},
+      {SqlInfoOptions::SqlInfo::SQL_IDENTIFIER_QUOTE_CHAR,
+       SqlInfoResult(std::string("\""))},
+      {SqlInfoOptions::SqlInfo::SQL_QUOTED_IDENTIFIER_CASE,
+       SqlInfoResult(int64_t(SqlInfoOptions::SqlSupportedCaseSensitivity::
+                                 SQL_CASE_SENSITIVITY_CASE_INSENSITIVE))},
+      {SqlInfoOptions::SqlInfo::SQL_ALL_TABLES_ARE_SELECTABLE, SqlInfoResult(true)},
+      {SqlInfoOptions::SqlInfo::SQL_NULL_ORDERING,
+       SqlInfoResult(
+           int64_t(SqlInfoOptions::SqlNullOrdering::SQL_NULLS_SORTED_AT_START))},
+      {SqlInfoOptions::SqlInfo::SQL_KEYWORDS,
+       SqlInfoResult(std::vector<std::string>({"ABORT",
+                                               "ACTION",
+                                               "ADD",
+                                               "AFTER",
+                                               "ALL",
+                                               "ALTER",
+                                               "ALWAYS",
+                                               "ANALYZE",
+                                               "AND",
+                                               "AS",
+                                               "ASC",
+                                               "ATTACH",
+                                               "AUTOINCREMENT",
+                                               "BEFORE",
+                                               "BEGIN",
+                                               "BETWEEN",
+                                               "BY",
+                                               "CASCADE",
+                                               "CASE",
+                                               "CAST",
+                                               "CHECK",
+                                               "COLLATE",
+                                               "COLUMN",
+                                               "COMMIT",
+                                               "CONFLICT",
+                                               "CONSTRAINT",
+                                               "CREATE",
+                                               "CROSS",
+                                               "CURRENT",
+                                               "CURRENT_DATE",
+                                               "CURRENT_TIME",
+                                               "CURRENT_TIMESTAMP",
+                                               "DATABASE",
+                                               "DEFAULT",
+                                               "DEFERRABLE",
+                                               "DEFERRED",
+                                               "DELETE",
+                                               "DESC",
+                                               "DETACH",
+                                               "DISTINCT",
+                                               "DO",
+                                               "DROP",
+                                               "EACH",
+                                               "ELSE",
+                                               "END",
+                                               "ESCAPE",
+                                               "EXCEPT",
+                                               "EXCLUDE",
+                                               "EXCLUSIVE",
+                                               "EXISTS",
+                                               "EXPLAIN",
+                                               "FAIL",
+                                               "FILTER",
+                                               "FIRST",
+                                               "FOLLOWING",
+                                               "FOR",
+                                               "FOREIGN",
+                                               "FROM",
+                                               "FULL",
+                                               "GENERATED",
+                                               "GLOB",
+                                               "GROUP",
+                                               "GROUPS",
+                                               "HAVING",
+                                               "IF",
+                                               "IGNORE",
+                                               "IMMEDIATE",
+                                               "IN",
+                                               "INDEX",
+                                               "INDEXED",
+                                               "INITIALLY",
+                                               "INNER",
+                                               "INSERT",
+                                               "INSTEAD",
+                                               "INTERSECT",
+                                               "INTO",
+                                               "IS",
+                                               "ISNULL",
+                                               "JOIN",
+                                               "KEY",
+                                               "LAST",
+                                               "LEFT",
+                                               "LIKE",
+                                               "LIMIT",
+                                               "MATCH",
+                                               "MATERIALIZED",
+                                               "NATURAL",
+                                               "NO",
+                                               "NOT",
+                                               "NOTHING",
+                                               "NOTNULL",
+                                               "NULL",
+                                               "NULLS",
+                                               "OF",
+                                               "OFFSET",
+                                               "ON",
+                                               "OR",
+                                               "ORDER",
+                                               "OTHERS",
+                                               "OUTER",
+                                               "OVER",
+                                               "PARTITION",
+                                               "PLAN",
+                                               "PRAGMA",
+                                               "PRECEDING",
+                                               "PRIMARY",
+                                               "QUERY",
+                                               "RAISE",
+                                               "RANGE",
+                                               "RECURSIVE",
+                                               "REFERENCES",
+                                               "REGEXP",
+                                               "REINDEX",
+                                               "RELEASE",
+                                               "RENAME",
+                                               "REPLACE",
+                                               "RESTRICT",
+                                               "RETURNING",
+                                               "RIGHT",
+                                               "ROLLBACK",
+                                               "ROW",
+                                               "ROWS",
+                                               "SAVEPOINT",
+                                               "SELECT",
+                                               "SET",
+                                               "TABLE",
+                                               "TEMP",
+                                               "TEMPORARY",
+                                               "THEN",
+                                               "TIES",
+                                               "TO",
+                                               "TRANSACTION",
+                                               "TRIGGER",
+                                               "UNBOUNDED",
+                                               "UNION",
+                                               "UNIQUE",
+                                               "UPDATE",
+                                               "USING",
+                                               "VACUUM",
+                                               "VALUES",
+                                               "VIEW",
+                                               "VIRTUAL",
+                                               "WHEN",
+                                               "WHERE",
+                                               "WINDOW",
+                                               "WITH",
+                                               "WITHOUT"}))},
+      {SqlInfoOptions::SqlInfo::SQL_NUMERIC_FUNCTIONS,
+       SqlInfoResult(std::vector<std::string>(
+           {"acos",    "acosh", "asin", "asinh",   "atan", "atan2", "atanh", "ceil",
+            "ceiling", "cos",   "cosh", "degrees", "exp",  "floor", "ln",    "log",
+            "log",     "log10", "log2", "mod",     "pi",   "pow",   "power", "radians",
+            "sin",     "sinh",  "sqrt", "tan",     "tanh", "trunc"}))},

Review comment:
       I'm curious: any particular reason these are lowercase, unlike the other entries here?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-983838760


   Hmm, I have 1.28.6:
   
   ```
   > docker-compose --version
   docker-compose version 1.28.6, build 5db8d86f
   ```
   
   You could also try the `--using-docker-cli` option with Archery.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-954166065


   Hey @lidavidm , we managed to remove the templating on client! Can you please take a look?
   
   Still need to fix the protobuf issue


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r738772484



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+               STATIC_LINK_LIBS
+               ${ARROW_FLIGHT_SQL_TEST_LINK_LIBS}
+               GTest::gtest
+               GTest::gmock
+               LABELS
+               "arrow_flight_sql")
+
+add_executable(flight_sql_test_app test_app_cli.cc
+                                   ${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc)
+target_link_libraries(flight_sql_test_app PRIVATE arrow_flight_sql_static
+                                                  ${GFLAGS_LIBRARIES})
+
+find_package(SQLite3)
+include_directories(${SQLite3_INCLUDE_DIRS})
+
+add_executable(flight_sql_test_server
+               server.cc
+               test_server_cli.cc
+               example/sqlite_statement.cc
+               example/sqlite_statement_batch_reader.cc
+               example/sqlite_server.cc
+               example/sqlite_tables_schema_batch_reader.cpp
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc")
+target_link_libraries(flight_sql_test_server
+                      PRIVATE arrow_flight_sql_static ${GFLAGS_LIBRARIES}
+                              ${SQLite3_LIBRARIES})

Review comment:
       Oh sorry, I missed that - that should be all then, thanks for fixing this.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r742111758



##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Hey @lidavidm ! Can you please clarify?

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       We are defining FlightClientImpl on `client_test.cc` and `client_internal.cc`, made sure that we are not building or linking them at any time on CMakeLists.txt

##########
File path: cpp/src/arrow/flight/flight-sql/client_test.cc
##########
@@ -0,0 +1,569 @@
+// 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/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/flight-sql/api.h>
+#include <arrow/testing/gtest_util.h>
+#include <gmock/gmock.h>
+#include <google/protobuf/any.pb.h>
+#include <gtest/gtest.h>
+
+#include <utility>
+
+namespace pb = arrow::flight::protocol;
+using ::testing::_;
+using ::testing::Ref;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+
+namespace internal {
+class FlightClientImpl {
+ public:
+  ~FlightClientImpl() = default;
+
+  MOCK_METHOD(Status, GetFlightInfo,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               std::unique_ptr<FlightInfo>*));
+  MOCK_METHOD(Status, DoGet,
+              (const FlightCallOptions& options, const Ticket& ticket,
+               std::unique_ptr<FlightStreamReader>* stream));
+  MOCK_METHOD(Status, DoPut,
+              (const FlightCallOptions&, const FlightDescriptor&,
+               const std::shared_ptr<Schema>& schema,
+               std::unique_ptr<FlightStreamWriter>*,
+               std::unique_ptr<FlightMetadataReader>*));
+  MOCK_METHOD(Status, DoAction,
+              (const FlightCallOptions& options, const Action& action,
+               std::unique_ptr<ResultStream>* results));
+};
+
+Status FlightClientImpl_GetFlightInfo(FlightClientImpl* client,
+                                      const FlightCallOptions& options,
+                                      const FlightDescriptor& descriptor,
+                                      std::unique_ptr<FlightInfo>* info) {
+  return client->GetFlightInfo(options, descriptor, info);
+}
+
+Status FlightClientImpl_DoPut(FlightClientImpl* client, const FlightCallOptions& options,
+                              const FlightDescriptor& descriptor,
+                              const std::shared_ptr<Schema>& schema,
+                              std::unique_ptr<FlightStreamWriter>* stream,
+                              std::unique_ptr<FlightMetadataReader>* reader) {
+  return client->DoPut(options, descriptor, schema, stream, reader);
+}
+
+Status FlightClientImpl_DoGet(FlightClientImpl* client, const FlightCallOptions& options,
+                              const Ticket& ticket,
+                              std::unique_ptr<FlightStreamReader>* stream) {
+  return client->DoGet(options, ticket, stream);
+}
+
+Status FlightClientImpl_DoAction(FlightClientImpl* client,
+                                 const FlightCallOptions& options, const Action& action,
+                                 std::unique_ptr<ResultStream>* results) {
+  return client->DoAction(options, action, results);
+}
+
+}  // namespace internal
+
+class FlightMetadataReaderMock : public FlightMetadataReader {
+ public:
+  std::shared_ptr<Buffer>* buffer;
+
+  explicit FlightMetadataReaderMock(std::shared_ptr<Buffer>* buffer) {
+    this->buffer = buffer;
+  }
+
+  Status ReadMetadata(std::shared_ptr<Buffer>* out) override {
+    *out = *buffer;
+    return Status::OK();
+  }
+};
+
+class FlightStreamWriterMock : public FlightStreamWriter {
+ public:
+  FlightStreamWriterMock() = default;
+
+  Status DoneWriting() override { return Status::OK(); }
+
+  Status WriteMetadata(std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema,
+               const ipc::IpcWriteOptions& options) override {
+    return Status::OK();
+  }
+
+  Status Begin(const std::shared_ptr<Schema>& schema) override {
+    return MetadataRecordBatchWriter::Begin(schema);
+  }
+
+  ipc::WriteStats stats() const override { return ipc::WriteStats(); }
+
+  Status WriteWithMetadata(const RecordBatch& batch,
+                           std::shared_ptr<Buffer> app_metadata) override {
+    return Status::OK();
+  }
+
+  Status Close() override { return Status::OK(); }
+
+  Status WriteRecordBatch(const RecordBatch& batch) override { return Status::OK(); }
+};
+
+FlightDescriptor getDescriptor(google::protobuf::Message& command) {
+  google::protobuf::Any any;
+  any.PackFrom(command);
+
+  const std::string& string = any.SerializeAsString();
+  return FlightDescriptor::Command(string);
+}
+
+TEST(TestFlightSqlClient, TestGetCatalogs) {
+  auto client_mock = std::make_shared<internal::FlightClientImpl>();
+  FlightSqlClient sql_client(client_mock);

Review comment:
       Oops, didn't see your last comment!
   I thought that as it was statically linking libarrow_flight_sql(containing client_internal.cc) when building client_test.cc it could be a problem.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734722860



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       A very strange bug occurred when we tried to link them together and also when we tried following the same approach as Flight (through `protocol_internal.cc`), the protobuf objects were not behaving correctly when a message had multiple string fields, my understanding of what went wrong is this:
   
   The problem was that as Arrow Flight implicitly static-links Protobuf (when compiling protocol_internal.cc), Arrow Flight SQL was linking it too by the same means and this ended up causing a one definition rule violation on an internal symbol of protobuf (google::protobuf::internal::GetEmptyStringAlreadyInited())
   
   Other person reported the exactly same issue here: https://github.com/protocolbuffers/protobuf/issues/6031




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] lidavidm commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
lidavidm commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r734745096



##########
File path: cpp/src/arrow/flight/flight-sql/client.h
##########
@@ -0,0 +1,260 @@
+// 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.
+
+#ifndef ARROW_FLIGHT_SQL_CLIENT_H
+#define ARROW_FLIGHT_SQL_CLIENT_H
+
+#include <arrow/flight/Flight.pb.h>
+#include <arrow/flight/client.h>
+#include <arrow/flight/flight-sql/FlightSql.pb.h>
+#include <arrow/flight/types.h>
+#include <arrow/status.h>
+#include <google/protobuf/message.h>
+
+namespace pb = arrow::flight::protocol;
+
+namespace arrow {
+namespace flight {
+namespace sql {
+namespace internal {
+
+template <class T = arrow::flight::FlightClient>
+class ARROW_EXPORT PreparedStatementT {

Review comment:
       You could also have this structure, I think:
   - client.h has an abstract base class and a function `MakePreparedStatement()`
   - client_internal.h has:
   
       ```cpp
   template <class T>
   class PreparedStatementImpl : public PreparedStatement {
   // ...current impl...
   };
       ```
   - In tests, include client_internal.h and instantiate `PreparedStatementImpl<MockClient>`
   - In client.cc, include client_internal.h and instantiate `PreparedStatementImpl<FlightClient>` to implement `MakePreparedStatement`
   
   (maybe a MakePreparedStatementImpl also needs to be templated and in client_internal.h) 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] rafael-telles commented on a change in pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
rafael-telles commented on a change in pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#discussion_r735789452



##########
File path: cpp/src/arrow/flight/flight-sql/CMakeLists.txt
##########
@@ -0,0 +1,112 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_custom_target(arrow_flight_sql)
+
+arrow_install_all_headers("arrow/flight/flight-sql")
+
+set(FLIGHT_SQL_PROTO_PATH "${ARROW_SOURCE_DIR}/../format")
+set(FLIGHT_SQL_PROTO ${ARROW_SOURCE_DIR}/../format/FlightSql.proto)
+
+set(FLIGHT_SQL_GENERATED_PROTO_FILES "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
+                                     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.h")
+
+set(PROTO_DEPENDS ${FLIGHT_SQL_PROTO} ${ARROW_PROTOBUF_LIBPROTOBUF} gRPC::grpc_cpp_plugin)
+
+add_custom_command(OUTPUT ${FLIGHT_SQL_GENERATED_PROTO_FILES}
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--cpp_out=${CMAKE_CURRENT_BINARY_DIR}" "${FLIGHT_SQL_PROTO}"
+                   DEPENDS ${PROTO_DEPENDS} ARGS
+                   COMMAND ${ARROW_PROTOBUF_PROTOC} "-I${FLIGHT_SQL_PROTO_PATH}"
+                           "--grpc_out=${CMAKE_CURRENT_BINARY_DIR}"
+                           "--plugin=protoc-gen-grpc=$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+                           "${FLIGHT_SQL_PROTO}")
+
+set_source_files_properties(${FLIGHT_SQL_GENERATED_PROTO_FILES} PROPERTIES GENERATED TRUE)
+
+add_custom_target(flight_sql_grpc_gen ALL DEPENDS ${FLIGHT_SQL_GENERATED_PROTO_FILES})
+
+# <KLUDGE> -Werror / /WX cause try_compile to fail because there seems to be no
+# way to pass -isystem $GRPC_INCLUDE_DIR instead of -I$GRPC_INCLUDE_DIR
+set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
+string(REPLACE "/WX" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+string(REPLACE "-Werror " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+
+set(ARROW_FLIGHT_SQL_SRCS server.cc)
+
+add_arrow_lib(arrow_flight_sql
+              CMAKE_PACKAGE_NAME
+              ArrowFlightSql
+              PKG_CONFIG_NAME
+              arrow-flight-sql
+              OUTPUTS
+              ARROW_FLIGHT_SQL_LIBRARIES
+              SOURCES
+              ${ARROW_FLIGHT_SQL_SRCS}
+              PRECOMPILED_HEADERS
+              "$<$<COMPILE_LANGUAGE:CXX>:arrow/flight/flight-sql/pch.h>"
+              DEPENDENCIES
+              flight_sql_grpc_gen
+              SHARED_LINK_FLAGS
+              ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in cpp/arrow/CMakeLists.txt
+              SHARED_LINK_LIBS
+              arrow_flight_shared
+              ${ARROW_FLIGHT_SQL_LINK_LIBS}
+              STATIC_LINK_LIBS
+              arrow_flight_static
+              ${ARROW_FLIGHT_SQL_LINK_LIBS})
+
+if(ARROW_TEST_LINKAGE STREQUAL "static")
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS
+      arrow_flight_sql_static arrow_flight_testing_static
+      ${ARROW_FLIGHT_STATIC_LINK_LIBS} ${ARROW_TEST_LINK_LIBS})
+else()
+  set(ARROW_FLIGHT_SQL_TEST_LINK_LIBS arrow_flight_sql_shared arrow_flight_testing_shared
+                                      ${ARROW_TEST_LINK_LIBS})
+endif()
+
+add_arrow_test(flight_sql_test
+               SOURCES
+               client_test.cc
+               server_test.cc
+               "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"

Review comment:
       Hi @lidavidm , I tried folding FlightSql into libarrow_flight, but it didn't work... I tried these two approaches:
   
   1 - include FlightSql on protocol_internal:
   ```diff
     #include "arrow/flight/Flight.grpc.pb.cc"  // NOLINT
     #include "arrow/flight/Flight.pb.cc"       // NOLINT
   + #include "arrow/flight/FlightSql.pb.cc"    // NOLINT
   ```
   This doesn't compile due to redefinition errors:
   ```
   error: redefinition of 'const google::protobuf::internal::MigrationSchema schemas []'
   ```
   
   2 - include FlightSql generated sources on CMakeLists:
   ```diff
     set(ARROW_FLIGHT_SRCS
         client.cc
         client_cookie_middleware.cc
         client_header_internal.cc
         internal.cc
         protocol_internal.cc
   +     "${CMAKE_CURRENT_BINARY_DIR}/FlightSql.pb.cc"
         serialization_internal.cc
         server.cc
         server_auth.cc
         types.cc)
   ```
   
   This compiles, but causes the same error as before (duplicate protobuf Symbol `GetEmptyStringAlreadyInited`)




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [arrow] pitrou edited a comment on pull request #11507: ARROW-14421: [C++] Implement Flight SQL

Posted by GitBox <gi...@apache.org>.
pitrou edited a comment on pull request #11507:
URL: https://github.com/apache/arrow/pull/11507#issuecomment-977865623


   I am reviewing the C++ parts, but briefly a high-level concern: the spec and/or the implementation seems to overload the term "schema" for a different thing than the usual concept of an Arrow schema (which exists in C++ but also in Java and in the Arrow format definition itself). Would it be possible to find another term?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org