This is an automated email from the ASF dual-hosted git repository.

kou pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 0061d79b4b GH-36408: [GLib][FlightSQL] Add support for 
INSERT/UPDATE/DELETE (#36409)
0061d79b4b is described below

commit 0061d79b4bfe1a7b3629ece0f4dc26daadff2789
Author: Sutou Kouhei <[email protected]>
AuthorDate: Sun Jul 2 07:18:47 2023 +0900

    GH-36408: [GLib][FlightSQL] Add support for INSERT/UPDATE/DELETE (#36409)
    
    ### Rationale for this change
    
    We need the bindings of them to support INSERT/UPDATE/DELETE:
    
    * `arrow::flight::sql::FlightSqlClient::ExecuteUpdate()`
    * `arrow::flight::sql::FlightSqlServerBase::DoPutCommandStatementUpdate()`
    
    ### What changes are included in this PR?
    
    The bindings of them.
    
    ### Are these changes tested?
    
    Yes.
    
    ### Are there any user-facing changes?
    
    Yes.
    * Closes: #36408
    
    Authored-by: Sutou Kouhei <[email protected]>
    Signed-off-by: Sutou Kouhei <[email protected]>
---
 c_glib/arrow-flight-sql-glib/client.cpp |  32 ++++++++++
 c_glib/arrow-flight-sql-glib/client.h   |   7 +++
 c_glib/arrow-flight-sql-glib/server.cpp | 101 ++++++++++++++++++++++++++++++++
 c_glib/arrow-flight-sql-glib/server.h   |  30 ++++++++++
 c_glib/arrow-flight-sql-glib/server.hpp |   7 +++
 c_glib/test/flight-sql/test-client.rb   |  14 +++++
 c_glib/test/helper/flight-sql-server.rb |   7 +++
 7 files changed, 198 insertions(+)

diff --git a/c_glib/arrow-flight-sql-glib/client.cpp 
b/c_glib/arrow-flight-sql-glib/client.cpp
index f316af8145..f05319532c 100644
--- a/c_glib/arrow-flight-sql-glib/client.cpp
+++ b/c_glib/arrow-flight-sql-glib/client.cpp
@@ -208,6 +208,38 @@ gaflightsql_client_execute(GAFlightSQLClient *client,
   return gaflight_info_new_raw(flight_info.release());
 }
 
+/**
+ * gaflightsql_client_execute_update:
+ * @client: A #GAFlightSQLClient.
+ * @query: A query to be executed in the UTF-8 format.
+ * @options: (nullable): A #GAFlightCallOptions.
+ * @error: (nullable): Return location for a #GError or %NULL.
+ *
+ * Returns: The number of changed records.
+ *
+ * Since: 13.0.0
+ */
+gint64
+gaflightsql_client_execute_update(GAFlightSQLClient *client,
+                                  const gchar *query,
+                                  GAFlightCallOptions *options,
+                                  GError **error)
+{
+  auto flight_sql_client = gaflightsql_client_get_raw(client);
+  arrow::flight::FlightCallOptions flight_default_options;
+  auto flight_options = &flight_default_options;
+  if (options) {
+    flight_options = gaflight_call_options_get_raw(options);
+  }
+  auto result = flight_sql_client->ExecuteUpdate(*flight_options, query);
+  if (!garrow::check(error,
+                     result,
+                     "[flight-sql-client][execute-update]")) {
+    return 0;
+  }
+  return *result;
+}
+
 /**
  * gaflightsql_client_do_get:
  * @client: A #GAFlightClient.
diff --git a/c_glib/arrow-flight-sql-glib/client.h 
b/c_glib/arrow-flight-sql-glib/client.h
index a962cad336..6374fece22 100644
--- a/c_glib/arrow-flight-sql-glib/client.h
+++ b/c_glib/arrow-flight-sql-glib/client.h
@@ -46,6 +46,13 @@ gaflightsql_client_execute(GAFlightSQLClient *client,
                            GAFlightCallOptions *options,
                            GError **error);
 
+GARROW_AVAILABLE_IN_13_0
+gint64
+gaflightsql_client_execute_update(GAFlightSQLClient *client,
+                                  const gchar *query,
+                                  GAFlightCallOptions *options,
+                                  GError **error);
+
 GARROW_AVAILABLE_IN_9_0
 GAFlightStreamReader *
 gaflightsql_client_do_get(GAFlightSQLClient *client,
diff --git a/c_glib/arrow-flight-sql-glib/server.cpp 
b/c_glib/arrow-flight-sql-glib/server.cpp
index 51cdb22ab5..750dff2232 100644
--- a/c_glib/arrow-flight-sql-glib/server.cpp
+++ b/c_glib/arrow-flight-sql-glib/server.cpp
@@ -126,6 +126,36 @@ 
gaflightsql_statement_query_get_query(GAFlightSQLStatementQuery *command)
 }
 
 
+G_DEFINE_TYPE(GAFlightSQLStatementUpdate,
+              gaflightsql_statement_update,
+              GAFLIGHTSQL_TYPE_COMMAND)
+
+static void
+gaflightsql_statement_update_init(GAFlightSQLStatementUpdate *object)
+{
+}
+
+static void
+gaflightsql_statement_update_class_init(GAFlightSQLStatementUpdateClass *klass)
+{
+}
+
+/**
+ * gaflightsql_statement_update_get_query:
+ * @command: A #GAFlightSQLStatementUpdate.
+ *
+ * Returns: The query to be executed.
+ *
+ * Since: 13.0.0
+ */
+const gchar *
+gaflightsql_statement_update_get_query(GAFlightSQLStatementUpdate *command)
+{
+  auto statement_update = gaflightsql_statement_update_get_raw(command);
+  return statement_update->query.c_str();
+}
+
+
 G_DEFINE_TYPE(GAFlightSQLStatementQueryTicket,
               gaflightsql_statement_query_ticket,
               GAFLIGHTSQL_TYPE_COMMAND)
@@ -250,6 +280,29 @@ namespace gaflightsql {
       return std::make_unique<gaflight::DataStream>(gastream);
     }
 
+    arrow::Result<int64_t>
+    DoPutCommandStatementUpdate(
+      const arrow::flight::ServerCallContext &context,
+      const arrow::flight::sql::StatementUpdate& command) override {
+      auto gacontext = gaflight_server_call_context_new_raw(&context);
+      auto gacommand = gaflightsql_statement_update_new_raw(&command);
+      GError *gerror = nullptr;
+      auto n_changed_records =
+        gaflightsql_server_do_put_command_statement_update(gaserver_,
+                                                           gacontext,
+                                                           gacommand,
+                                                           &gerror);
+      g_object_unref(gacommand);
+      g_object_unref(gacontext);
+      if (gerror) {
+        return garrow_error_to_status(
+          gerror,
+          arrow::StatusCode::UnknownError,
+          "[flight-sql-server][do-put-command-statement-update]");
+      }
+      return n_changed_records;
+    }
+
   private:
     GAFlightSQLServer *gaserver_;
   };
@@ -381,6 +434,35 @@ gaflightsql_server_do_get_statement(GAFlightSQLServer 
*server,
   return (*(klass->do_get_statement))(server, context, ticket, error);
 }
 
+/**
+ * gaflightsql_server_do_put_command_statement_update:
+ * @server: A #GAFlightServer.
+ * @context: A #GAFlightServerCallContext.
+ * @command: A #GAFlightSQLStatementUpdate.
+ * @error: (nullable): Return location for a #GError or %NULL.
+ *
+ * Returns: The number of changed records.
+ *
+ * Since: 13.0.0
+ */
+gint64
+gaflightsql_server_do_put_command_statement_update(
+  GAFlightSQLServer *server,
+  GAFlightServerCallContext *context,
+  GAFlightSQLStatementUpdate *command,
+  GError **error)
+{
+  auto klass = GAFLIGHTSQL_SERVER_GET_CLASS(server);
+  if (!(klass && klass->do_put_command_statement_update)) {
+    g_set_error(error,
+                GARROW_ERROR,
+                GARROW_ERROR_NOT_IMPLEMENTED,
+                "not implemented");
+    return 0;
+  }
+  return klass->do_put_command_statement_update(server, context, command, 
error);
+}
+
 
 G_END_DECLS
 
@@ -402,6 +484,25 @@ 
gaflightsql_statement_query_get_raw(GAFlightSQLStatementQuery *command)
   return static_cast<const arrow::flight::sql::StatementQuery 
*>(priv->command);
 }
 
+
+GAFlightSQLStatementUpdate *
+gaflightsql_statement_update_new_raw(
+  const arrow::flight::sql::StatementUpdate *flight_command)
+{
+  return GAFLIGHTSQL_STATEMENT_UPDATE(
+    g_object_new(GAFLIGHTSQL_TYPE_STATEMENT_UPDATE,
+                 "command", flight_command,
+                 nullptr));
+}
+
+const arrow::flight::sql::StatementUpdate *
+gaflightsql_statement_update_get_raw(GAFlightSQLStatementUpdate *command)
+{
+  auto priv = GAFLIGHTSQL_COMMAND_GET_PRIVATE(command);
+  return static_cast<const arrow::flight::sql::StatementUpdate 
*>(priv->command);
+}
+
+
 GAFlightSQLStatementQueryTicket *
 gaflightsql_statement_query_ticket_new_raw(
   const arrow::flight::sql::StatementQueryTicket *flight_command)
diff --git a/c_glib/arrow-flight-sql-glib/server.h 
b/c_glib/arrow-flight-sql-glib/server.h
index bc58f42aa2..60e5b300d4 100644
--- a/c_glib/arrow-flight-sql-glib/server.h
+++ b/c_glib/arrow-flight-sql-glib/server.h
@@ -52,6 +52,22 @@ const gchar *
 gaflightsql_statement_query_get_query(GAFlightSQLStatementQuery *command);
 
 
+#define GAFLIGHTSQL_TYPE_STATEMENT_UPDATE 
(gaflightsql_statement_update_get_type())
+G_DECLARE_DERIVABLE_TYPE(GAFlightSQLStatementUpdate,
+                         gaflightsql_statement_update,
+                         GAFLIGHTSQL,
+                         STATEMENT_UPDATE,
+                         GAFlightSQLCommand)
+struct _GAFlightSQLStatementUpdateClass
+{
+  GAFlightSQLCommandClass parent_class;
+};
+
+GARROW_AVAILABLE_IN_13_0
+const gchar *
+gaflightsql_statement_update_get_query(GAFlightSQLStatementUpdate *command);
+
+
 #define GAFLIGHTSQL_TYPE_STATEMENT_QUERY_TICKET         \
   (gaflightsql_statement_query_ticket_get_type())
 G_DECLARE_DERIVABLE_TYPE(GAFlightSQLStatementQueryTicket,
@@ -87,6 +103,8 @@ G_DECLARE_DERIVABLE_TYPE(GAFlightSQLServer,
  *   SQL query.
  * @do_get_statement: A virtual function to implement `DoGetStatement` API
  *   that gets a #GAFlightDataStream containing the query results.
+ * @do_put_command_statement_update: A virtual function to implement
+ *   `DoPutCommandStatementUpdate` API that executes an update SQL statement.
  *
  * Since: 9.0.0
  */
@@ -105,6 +123,11 @@ struct _GAFlightSQLServerClass
     GAFlightServerCallContext *context,
     GAFlightSQLStatementQueryTicket *ticket,
     GError **error);
+  gint64 (*do_put_command_statement_update)(
+    GAFlightSQLServer *server,
+    GAFlightServerCallContext *context,
+    GAFlightSQLStatementUpdate *command,
+    GError **error);
 };
 
 GARROW_AVAILABLE_IN_9_0
@@ -122,5 +145,12 @@ gaflightsql_server_do_get_statement(
   GAFlightServerCallContext *context,
   GAFlightSQLStatementQueryTicket *ticket,
   GError **error);
+GARROW_AVAILABLE_IN_13_0
+gint64
+gaflightsql_server_do_put_command_statement_update(
+  GAFlightSQLServer *server,
+  GAFlightServerCallContext *context,
+  GAFlightSQLStatementUpdate *command,
+  GError **error);
 
 G_END_DECLS
diff --git a/c_glib/arrow-flight-sql-glib/server.hpp 
b/c_glib/arrow-flight-sql-glib/server.hpp
index f516e2e78b..9159a66489 100644
--- a/c_glib/arrow-flight-sql-glib/server.hpp
+++ b/c_glib/arrow-flight-sql-glib/server.hpp
@@ -31,6 +31,13 @@ const arrow::flight::sql::StatementQuery *
 gaflightsql_statement_query_get_raw(
   GAFlightSQLStatementQuery *command);
 
+GAFlightSQLStatementUpdate *
+gaflightsql_statement_update_new_raw(
+  const arrow::flight::sql::StatementUpdate *flight_command);
+const arrow::flight::sql::StatementUpdate *
+gaflightsql_statement_update_get_raw(
+  GAFlightSQLStatementUpdate *command);
+
 GAFlightSQLStatementQueryTicket *
 gaflightsql_statement_query_ticket_new_raw(
   const arrow::flight::sql::StatementQueryTicket *flight_command);
diff --git a/c_glib/test/flight-sql/test-client.rb 
b/c_glib/test/flight-sql/test-client.rb
index c291ae5841..adfb47fe0b 100644
--- a/c_glib/test/flight-sql/test-client.rb
+++ b/c_glib/test/flight-sql/test-client.rb
@@ -53,4 +53,18 @@ class TestFlightSQLClient < Test::Unit::TestCase
       end
     end
   end
+
+  sub_test_case("#execute_update") do
+    def test_success
+      insert_sql = "INSERT INTO page_view_table VALUES (100, true)"
+      n_changed_records = @sql_client.execute_update(insert_sql)
+      assert_equal(1, n_changed_records)
+    end
+
+    def test_error
+      assert_raise(Arrow::Error::Invalid) do
+        @sql_client.execute_update("INSERT")
+      end
+    end
+  end
 end
diff --git a/c_glib/test/helper/flight-sql-server.rb 
b/c_glib/test/helper/flight-sql-server.rb
index 28e6010e93..8b664ca112 100644
--- a/c_glib/test/helper/flight-sql-server.rb
+++ b/c_glib/test/helper/flight-sql-server.rb
@@ -39,5 +39,12 @@ module Helper
       reader = Arrow::TableBatchReader.new(table)
       ArrowFlight::RecordBatchStream.new(reader)
     end
+
+    def virtual_do_do_put_command_statement_update(context, command)
+      unless command.query == "INSERT INTO page_view_table VALUES (100, true)"
+        raise Arrow::Error::Invalid.new("invalid SQL")
+      end
+      1
+    end
   end
 end

Reply via email to