You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@arrow.apache.org by ko...@apache.org on 2023/04/02 15:59:36 UTC
[arrow-adbc] branch main updated: feat(glib): add gadbc_connection_get_info() (#571)
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-adbc.git
The following commit(s) were added to refs/heads/main by this push:
new 140ed33 feat(glib): add gadbc_connection_get_info() (#571)
140ed33 is described below
commit 140ed330bb53206bf05c721d04507efd0fca0d6f
Author: Sutou Kouhei <ko...@clear-code.com>
AuthorDate: Mon Apr 3 00:59:30 2023 +0900
feat(glib): add gadbc_connection_get_info() (#571)
Fixes #548.
---
glib/adbc-glib/connection.c | 58 +++++++++++++++++++++++++++++++++++++++
glib/adbc-glib/connection.h | 31 +++++++++++++++++++++
glib/test/test-connection.rb | 56 ++++++++++++++++++++++++++++++++++++++
ruby/lib/adbc/connection.rb | 29 ++++++++++++++++++++
ruby/test/test-connection.rb | 65 ++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 239 insertions(+)
diff --git a/glib/adbc-glib/connection.c b/glib/adbc-glib/connection.c
index 0c83b1e..ebf4b61 100644
--- a/glib/adbc-glib/connection.c
+++ b/glib/adbc-glib/connection.c
@@ -183,6 +183,64 @@ gboolean gadbc_connection_init(GADBCConnection* connection, GADBCDatabase* datab
return success;
}
+/**
+ * gadbc_connection_get_info:
+ * @connection: A #GADBCConnection.
+ * @info_codes: (nullable) (array length=n_info_codes): A list of
+ * metadata codes to fetch, or %NULL to fetch all.
+ * @n_info_codes: The length of the info_codes parameter. Ignored if
+ * info_codes is %NULL.
+ * @error: (nullable): Return location for a #GError or %NULL.
+ *
+ * The result is an Arrow dataset with the following schema:
+ *
+ * Field Name | Field Type
+ * ----------------------------|------------------------
+ * info_name | uint32 not null
+ * info_value | INFO_SCHEMA
+ *
+ * INFO_SCHEMA is a dense union with members:
+ *
+ * Field Name (Type Code) | Field Type
+ * ----------------------------|------------------------
+ * string_value (0) | utf8
+ * bool_value (1) | bool
+ * int64_value (2) | int64
+ * int32_bitmask (3) | int32
+ * string_list (4) | list<utf8>
+ * int32_to_int32_list_map (5) | map<int32, list<int32>>
+ *
+ * Each metadatum is identified by an integer code. The recognized
+ * codes are defined as constants. Codes [0, 10_000) are reserved
+ * for ADBC usage. Drivers/vendors will ignore requests for
+ * unrecognized codes (the row will be omitted from the result).
+ *
+ * Returns: The result set as `struct ArrowArrayStream *`. It should
+ * be freed with the `ArrowArrayStream::release` callback then
+ * g_free() when no longer needed.
+ *
+ * Since: 0.4.0
+ */
+gpointer gadbc_connection_get_info(GADBCConnection* connection, guint32* info_codes,
+ gsize n_info_codes, GError** error) {
+ const gchar* context = "[adbc][connection][get-info]";
+ struct AdbcConnection* adbc_connection =
+ gadbc_connection_get_raw(connection, context, error);
+ if (!adbc_connection) {
+ return NULL;
+ }
+ struct ArrowArrayStream* array_stream = g_new0(struct ArrowArrayStream, 1);
+ struct AdbcError adbc_error = {};
+ AdbcStatusCode status_code = AdbcConnectionGetInfo(
+ adbc_connection, info_codes, n_info_codes, array_stream, &adbc_error);
+ if (gadbc_error_check(error, status_code, &adbc_error, context)) {
+ return array_stream;
+ } else {
+ g_free(array_stream);
+ return NULL;
+ }
+}
+
/**
* gadbc_connection_get_table_types:
* @connection: A #GADBCConnection.
diff --git a/glib/adbc-glib/connection.h b/glib/adbc-glib/connection.h
index 50d1a15..a5c3868 100644
--- a/glib/adbc-glib/connection.h
+++ b/glib/adbc-glib/connection.h
@@ -23,6 +23,34 @@
G_BEGIN_DECLS
+/**
+ * GADBCInfo:
+ * @GADBC_INFO_VENDOR_NAME: The database vendor/product name (e.g. the
+ * server name). (type: utf8).
+ * @GADBC_INFO_VENDOR_VERSION: The database vendor/product library version
+ * (type: utf8).
+ * @GADBC_INFO_VENDOR_ARROW_VERSION: The database vendor/product Arrow
+ * library version (type: utf8).
+ * @GADBC_INFO_DRIVER_NAME: The driver name (type: utf8).
+ * @GADBC_INFO_DRIVER_VERSION: The driver version (type: utf8).
+ * @GADBC_INFO_DRIVER_ARROW_VERSION: The driver Arrow library version
+ * (type: utf8).
+ *
+ * The information code that is used by gadbc_connection_get_info().
+ *
+ * They are corresponding to `ADBC_INFO_*` values.
+ *
+ * Since: 0.4.0
+ */
+typedef enum {
+ GADBC_INFO_VENDOR_NAME = 0,
+ GADBC_INFO_VENDOR_VERSION = 1,
+ GADBC_INFO_VENDOR_ARROW_VERSION = 2,
+ GADBC_INFO_DRIVER_NAME = 100,
+ GADBC_INFO_DRIVER_VERSION = 101,
+ GADBC_INFO_DRIVER_ARROW_VERSION = 102,
+} GADBCInfo;
+
#define GADBC_TYPE_CONNECTION (gadbc_connection_get_type())
G_DECLARE_DERIVABLE_TYPE(GADBCConnection, gadbc_connection, GADBC, CONNECTION, GObject)
struct _GADBCConnectionClass {
@@ -41,6 +69,9 @@ gboolean gadbc_connection_init(GADBCConnection* connection, GADBCDatabase* datab
GError** error);
GADBC_AVAILABLE_IN_0_4
+gpointer gadbc_connection_get_info(GADBCConnection* connection, guint32* info_codes,
+ gsize n_info_codes, GError** error);
+GADBC_AVAILABLE_IN_0_4
gpointer gadbc_connection_get_table_types(GADBCConnection* connection, GError** error);
G_END_DECLS
diff --git a/glib/test/test-connection.rb b/glib/test/test-connection.rb
index c219178..130f2a0 100644
--- a/glib/test/test-connection.rb
+++ b/glib/test/test-connection.rb
@@ -30,6 +30,62 @@ class ConnectionTest < Test::Unit::TestCase
end
end
+ def normalize_version(version)
+ return nil if version.nil?
+ version.gsub(/\A\d+\.\d+\.\d+(?:-SNAPSHOT)?\z/, "X.Y.Z")
+ end
+
+ def normalize_info(info)
+ info.collect do |code, value|
+ value = value.values[0] if value.is_a?(Hash)
+ case code
+ when ADBC::Info::VENDOR_VERSION,
+ ADBC::Info::DRIVER_ARROW_VERSION
+ value = normalize_version(value)
+ end
+ [code, value]
+ end
+ end
+
+ sub_test_case("#get_info") do
+ def test_all
+ c_abi_array_stream = @connection.get_info
+ begin
+ reader = Arrow::RecordBatchReader.import(c_abi_array_stream)
+ table = reader.read_all
+ assert_equal([
+ [ADBC::Info::VENDOR_NAME, "SQLite"],
+ [ADBC::Info::VENDOR_VERSION, "X.Y.Z"],
+ [ADBC::Info::DRIVER_NAME, "ADBC SQLite Driver"],
+ [ADBC::Info::DRIVER_VERSION, "(unknown)"],
+ [ADBC::Info::DRIVER_ARROW_VERSION, "X.Y.Z"],
+ ],
+ normalize_info(table.raw_records))
+ ensure
+ GLib.free(c_abi_array_stream)
+ end
+ end
+
+ def test_multiple
+ codes = [
+ ADBC::Info::VENDOR_NAME,
+ ADBC::Info::DRIVER_NAME,
+ ]
+ c_abi_array_stream = @connection.get_info(codes)
+ begin
+ reader = Arrow::RecordBatchReader.import(c_abi_array_stream)
+ table = reader.read_all
+ assert_equal([
+ [ADBC::Info::VENDOR_NAME, "SQLite"],
+ [ADBC::Info::DRIVER_NAME, "ADBC SQLite Driver"],
+ ],
+ normalize_info(table.raw_records))
+ ensure
+ GLib.free(c_abi_array_stream)
+ end
+ end
+ end
+
def test_table_types
c_abi_array_stream = @connection.table_types
begin
diff --git a/ruby/lib/adbc/connection.rb b/ruby/lib/adbc/connection.rb
index eeed95c..739f611 100644
--- a/ruby/lib/adbc/connection.rb
+++ b/ruby/lib/adbc/connection.rb
@@ -32,5 +32,34 @@ module ADBC
statement.ingest(table_name, values, mode: mode)
end
end
+
+ def info(codes=nil)
+ unless codes.nil?
+ codes = codes.collect do |code|
+ ADBC::Info.try_convert(code)
+ end
+ end
+ c_abi_array_stream = get_info(codes)
+ begin
+ reader = Arrow::RecordBatchReader.import(c_abi_array_stream)
+ table = reader.read_all
+ values = {}
+ table.raw_records.each do |code, value|
+ value = value.values[0] if value.is_a?(Hash)
+ code = ADBC::Info.try_convert(code)
+ values[code.nick.gsub("-", "_").to_sym] = value
+ end
+ values
+ ensure
+ GLib.free(c_abi_array_stream)
+ end
+ end
+
+ ADBC::Info.values.each do |value|
+ name = value.nick.gsub("-", "_").to_sym
+ define_method(name) do
+ info([name])[name]
+ end
+ end
end
end
diff --git a/ruby/test/test-connection.rb b/ruby/test/test-connection.rb
index 2568035..4541449 100644
--- a/ruby/test/test-connection.rb
+++ b/ruby/test/test-connection.rb
@@ -52,4 +52,69 @@ class ConnectionTest < Test::Unit::TestCase
@connection.query("SELECT 1"))
end
end
+
+ sub_test_case("#info") do
+ def test_all
+ info = @connection.info
+ [
+ :vendor_version,
+ :driver_arrow_version,
+ ].each do |version_name|
+ next unless info.key?(version_name)
+ info[version_name] = normalize_version(info[version_name])
+ end
+ assert_equal({
+ vendor_name: "SQLite",
+ vendor_version: "X.Y.Z",
+ driver_name: "ADBC SQLite Driver",
+ driver_version: "(unknown)",
+ driver_arrow_version: "X.Y.Z"
+ },
+ info)
+ end
+
+ def test_integer
+ assert_equal({vendor_name: "SQLite"},
+ @connection.info([ADBC::Info::VENDOR_NAME]))
+ end
+
+ def test_symbol
+ assert_equal({vendor_name: "SQLite"},
+ @connection.info([:vendor_name]))
+ end
+
+ def test_STRING
+ assert_equal({vendor_name: "SQLite"},
+ @connection.info(["VENDOR_NAME"]))
+ end
+ end
+
+ def test_vendor_name
+ assert_equal("SQLite", @connection.vendor_name)
+ end
+
+ def test_vendor_version
+ assert_equal("X.Y.Z", normalize_version(@connection.vendor_version))
+ end
+
+ def test_vendor_arrow_version
+ assert_equal(nil, normalize_version(@connection.vendor_arrow_version))
+ end
+
+ def test_driver_name
+ assert_equal("ADBC SQLite Driver", @connection.driver_name)
+ end
+
+ def test_driver_version
+ assert_equal("(unknown)", normalize_version(@connection.driver_version))
+ end
+
+ def test_driver_arrow_version
+ assert_equal("X.Y.Z", normalize_version(@connection.driver_arrow_version))
+ end
+
+ private
+ def normalize_version(version)
+ version&.gsub(/\A\d+\.\d+\.\d+(?:-SNAPSHOT)?\z/, "X.Y.Z")
+ end
end