From 6819271274f4e58b0a35935b3d74b971a24a8d00 Mon Sep 17 00:00:00 2001 From: Sutou Kouhei Date: Sun, 14 Jan 2024 08:34:32 +0900 Subject: [PATCH] feat(glib): Add Apache Arrow GLib integration library Fixes #1280. We can use `GArrowRecordBatch`/`GArrowSchema`/`GArrowRecordBatchReader` instead of C data API with this library. --- ci/linux-packages/debian/control | 55 ++++++ .../debian/gir1.2-adbc-arrow-1.0.install | 1 + .../debian/libadbc-arrow-glib-dev.install | 6 + .../debian/libadbc-arrow-glib-doc.install | 1 + .../debian/libadbc-arrow-glib0.install | 1 + .../debian/libadbc-glib-dev.install | 2 +- ci/linux-packages/yum/almalinux-8/Dockerfile | 1 + ci/linux-packages/yum/almalinux-9/Dockerfile | 1 + .../yum/apache-arrow-adbc.spec.in | 57 +++++- dev/release/verify-apt.sh | 8 + dev/release/verify-yum.sh | 10 +- glib/adbc-arrow-glib/adbc-arrow-glib.h | 24 +++ glib/adbc-arrow-glib/meson.build | 115 ++++++++++++ glib/adbc-arrow-glib/statement.c | 146 +++++++++++++++ glib/adbc-arrow-glib/statement.h | 52 ++++++ glib/adbc-arrow-glib/version.h.in | 171 ++++++++++++++++++ glib/adbc-glib/statement.c | 49 +++-- glib/adbc-glib/statement.h | 4 + glib/adbc-glib/version.h.in | 23 +++ glib/example/vala/meson.build | 3 +- glib/example/vala/sqlite.vala | 15 +- glib/meson.build | 9 + glib/test/run.rb | 5 + glib/test/run.sh | 1 + glib/test/test-arrow-statement.rb | 80 ++++++++ glib/test/test-statement.rb | 2 - ruby/dependency-check/Rakefile | 6 +- ruby/lib/adbc.rb | 12 +- ruby/lib/adbc/arrow-statement.rb | 65 +++++++ ruby/lib/adbc/loader.rb | 19 ++ ruby/lib/adbc/statement-openable.rb | 33 ++++ ruby/lib/adbc/statement-operations.rb | 33 ++++ ruby/lib/adbc/statement.rb | 39 +--- 33 files changed, 982 insertions(+), 67 deletions(-) create mode 100644 ci/linux-packages/debian/gir1.2-adbc-arrow-1.0.install create mode 100644 ci/linux-packages/debian/libadbc-arrow-glib-dev.install create mode 100644 ci/linux-packages/debian/libadbc-arrow-glib-doc.install create mode 100644 ci/linux-packages/debian/libadbc-arrow-glib0.install create mode 100644 glib/adbc-arrow-glib/adbc-arrow-glib.h create mode 100644 glib/adbc-arrow-glib/meson.build create mode 100644 glib/adbc-arrow-glib/statement.c create mode 100644 glib/adbc-arrow-glib/statement.h create mode 100644 glib/adbc-arrow-glib/version.h.in create mode 100644 glib/test/test-arrow-statement.rb create mode 100644 ruby/lib/adbc/arrow-statement.rb create mode 100644 ruby/lib/adbc/statement-openable.rb create mode 100644 ruby/lib/adbc/statement-operations.rb diff --git a/ci/linux-packages/debian/control b/ci/linux-packages/debian/control index 3643c33737..2572edbad3 100644 --- a/ci/linux-packages/debian/control +++ b/ci/linux-packages/debian/control @@ -24,6 +24,7 @@ Build-Depends: debhelper-compat (= 12), gobject-introspection, golang | golang-1.20, + libarrow-glib-dev, libgirepository1.0-dev, libpq-dev, libsqlite3-dev, @@ -197,3 +198,57 @@ Recommends: Description: Apache Arrow Database Connectivity (ADBC) driver manager . This package provides documentations. + +Package: libadbc-arrow-glib0 +Section: libs +Architecture: any +Multi-Arch: same +Pre-Depends: ${misc:Pre-Depends} +Depends: + ${misc:Depends}, + ${shlibs:Depends}, + libadbc-glib0 (= ${binary:Version}) +Description: Apache Arrow Database Connectivity (ADBC) driver manager + . + This package provides library files for Apache Arrow GLib integration. + +Package: gir1.2-adbc-arrow-1.0 +Section: introspection +Architecture: any +Multi-Arch: same +Depends: + ${gir:Depends}, + ${misc:Depends}, + gir1.2-adbc-1.0 (= ${binary:Version}) +Description: Apache Arrow Database Connectivity (ADBC) driver manager + . + This package provides GObject Introspection typelib files for Apache + Arrow GLib integration. + +Package: libadbc-arrow-glib-dev +Section: libdevel +Architecture: any +Multi-Arch: same +Depends: + ${misc:Depends}, + gir1.2-adbc-arrow-1.0 (= ${binary:Version}), + libadbc-glib-dev (= ${binary:Version}) +Description: Apache Arrow Database Connectivity (ADBC) driver manager + . + This package provides header files for Apache Arrow GLib + integration. + +Package: libadbc-arrow-glib-doc +Section: doc +Architecture: all +Multi-Arch: foreign +Depends: + ${misc:Depends} +Recommends: + libglib2.0-doc, + libadbc-glib-doc, + libarrow-glib-doc +Description: Apache Arrow Database Connectivity (ADBC) driver manager + . + This package provides documentations for Apache Arrow GLib + integration. diff --git a/ci/linux-packages/debian/gir1.2-adbc-arrow-1.0.install b/ci/linux-packages/debian/gir1.2-adbc-arrow-1.0.install new file mode 100644 index 0000000000..800739d56a --- /dev/null +++ b/ci/linux-packages/debian/gir1.2-adbc-arrow-1.0.install @@ -0,0 +1 @@ +usr/lib/*/girepository-1.0/ADBCArrow-*.typelib diff --git a/ci/linux-packages/debian/libadbc-arrow-glib-dev.install b/ci/linux-packages/debian/libadbc-arrow-glib-dev.install new file mode 100644 index 0000000000..84f304c42f --- /dev/null +++ b/ci/linux-packages/debian/libadbc-arrow-glib-dev.install @@ -0,0 +1,6 @@ +usr/include/adbc-arrow-glib/ +usr/lib/*/libadbc-arrow-glib.so +usr/lib/*/pkgconfig/adbc-arrow-glib.pc +usr/share/adbc-arrow-glib/example/ +usr/share/gir-1.0/ADBCArrow-*.gir +usr/share/vala/vapi/adbc-arrow-glib.* diff --git a/ci/linux-packages/debian/libadbc-arrow-glib-doc.install b/ci/linux-packages/debian/libadbc-arrow-glib-doc.install new file mode 100644 index 0000000000..b5f85b4d28 --- /dev/null +++ b/ci/linux-packages/debian/libadbc-arrow-glib-doc.install @@ -0,0 +1 @@ +usr/share/doc/adbc-arrow-glib/ diff --git a/ci/linux-packages/debian/libadbc-arrow-glib0.install b/ci/linux-packages/debian/libadbc-arrow-glib0.install new file mode 100644 index 0000000000..b7d8187f50 --- /dev/null +++ b/ci/linux-packages/debian/libadbc-arrow-glib0.install @@ -0,0 +1 @@ +usr/lib/*/libadbc-arrow-glib.so.* diff --git a/ci/linux-packages/debian/libadbc-glib-dev.install b/ci/linux-packages/debian/libadbc-glib-dev.install index 7e5f0d8dcc..9ff7ea31b6 100644 --- a/ci/linux-packages/debian/libadbc-glib-dev.install +++ b/ci/linux-packages/debian/libadbc-glib-dev.install @@ -3,4 +3,4 @@ usr/lib/*/libadbc-glib.so usr/lib/*/pkgconfig/adbc-glib.pc usr/share/adbc-glib/example/ usr/share/gir-1.0/ADBC-*.gir -usr/share/vala/vapi/* +usr/share/vala/vapi/adbc-glib.* diff --git a/ci/linux-packages/yum/almalinux-8/Dockerfile b/ci/linux-packages/yum/almalinux-8/Dockerfile index dfd10dd449..8768d9ff6c 100644 --- a/ci/linux-packages/yum/almalinux-8/Dockerfile +++ b/ci/linux-packages/yum/almalinux-8/Dockerfile @@ -25,6 +25,7 @@ RUN \ yum install -y ${quiet} epel-release && \ yum install -y https://apache.jfrog.io/artifactory/arrow/almalinux/$(cut -d: -f5 /etc/system-release-cpe | cut -d. -f1)/apache-arrow-release-latest.rpm && \ yum install --enablerepo=powertools -y ${quiet} \ + arrow-glib-devel \ ccache \ cmake \ gcc-c++ \ diff --git a/ci/linux-packages/yum/almalinux-9/Dockerfile b/ci/linux-packages/yum/almalinux-9/Dockerfile index 213590e88a..7d1929e459 100644 --- a/ci/linux-packages/yum/almalinux-9/Dockerfile +++ b/ci/linux-packages/yum/almalinux-9/Dockerfile @@ -25,6 +25,7 @@ RUN \ dnf install -y ${quiet} epel-release && \ dnf install -y https://apache.jfrog.io/artifactory/arrow/almalinux/$(cut -d: -f5 /etc/system-release-cpe | cut -d. -f1)/apache-arrow-release-latest.rpm && \ dnf install --enablerepo=crb -y ${quiet} \ + arrow-glib-devel \ ccache \ cmake \ gcc-c++ \ diff --git a/ci/linux-packages/yum/apache-arrow-adbc.spec.in b/ci/linux-packages/yum/apache-arrow-adbc.spec.in index 7a50a1fe2e..d1ba2d6a93 100644 --- a/ci/linux-packages/yum/apache-arrow-adbc.spec.in +++ b/ci/linux-packages/yum/apache-arrow-adbc.spec.in @@ -40,6 +40,7 @@ License: Apache-2.0 URL: https://arrow.apache.org/adbc/ Source0: https://www.apache.org/dyn/closer.lua?action=download&path=/arrow/arrow-adbc-%{version}/apache-arrow-adbc-%{version}.tar.gz +BuildRequires: arrow-glib-devel BuildRequires: cmake BuildRequires: gcc-c++ BuildRequires: gobject-introspection-devel @@ -260,7 +261,7 @@ This package contains the libraries for ADBC GLib. %defattr(-,root,root,-) %doc README.md %license LICENSE.txt NOTICE.txt -%{_libdir}/girepository-1.0/ +%{_libdir}/girepository-1.0/ADBC-*.typelib %{_libdir}/libadbc-glib.so.* %package glib-devel @@ -278,8 +279,8 @@ Libraries and header files for ADBC GLib. %defattr(-,root,root,-) %doc README.md %license LICENSE.txt NOTICE.txt -%{_datadir}/gir-1.0/ -%{_datadir}/vala/vapi/ +%{_datadir}/gir-1.0/ADBC-*.gir +%{_datadir}/vala/vapi/adbc-glib.* %{_includedir}/adbc-glib/ %{_libdir}/libadbc-glib.a %{_libdir}/libadbc-glib.so @@ -299,6 +300,56 @@ Documentation for ADBC GLib. %{_datadir}/adbc-glib/example/ %{_docdir}/adbc-glib/ +%package arrow-glib%{major_version}-libs +Summary: Runtime libraries for Apache Arrow GLib integration +License: Apache-2.0 +Requires: %{name}-glib%{major_version}-libs = %{version}-%{release} + +%description arrow-glib%{major_version}-libs +This package contains the libraries for Apache Arrow GLib integration. + +%files arrow-glib%{major_version}-libs +%defattr(-,root,root,-) +%doc README.md +%license LICENSE.txt NOTICE.txt +%{_libdir}/girepository-1.0/ADBCArrow-*.typelib +%{_libdir}/libadbc-arrow-glib.so.* + +%package arrow-glib-devel +Summary: Libraries and header files for Apache Arrow GLib integration +License: Apache-2.0 +Requires: %{name}-arrow-glib%{major_version}-libs = %{version}-%{release} +Requires: %{name}-glib-devel = %{version}-%{release} +Requires: arrow-glib-devel + +%description arrow-glib-devel +Libraries and header files for Apache Arrow GLib integration + +%files arrow-glib-devel +%defattr(-,root,root,-) +%doc README.md +%license LICENSE.txt NOTICE.txt +%{_datadir}/gir-1.0/ADBCArrow-*.gir +%{_datadir}/vala/vapi/adbc-arrow-glib.* +%{_includedir}/adbc-arrow-glib/ +%{_libdir}/libadbc-arrow-glib.a +%{_libdir}/libadbc-arrow-glib.so +%{_libdir}/pkgconfig/adbc-arrow-glib.pc + +%package arrow-glib-doc +Summary: Documentation for Apache Arrow GLib integration +License: Apache-2.0 + +%description arrow-glib-doc +Documentation for Apache Arrow GLib integration. + +%files arrow-glib-doc +%defattr(-,root,root,-) +%doc README.md +%license LICENSE.txt NOTICE.txt +%{_datadir}/adbc-arrow-glib/example/ +%{_docdir}/adbc-arrow-glib/ + %changelog * Thu Apr 27 2023 Matt Topol - 0.4.0-1 - Add snowflake driver diff --git a/dev/release/verify-apt.sh b/dev/release/verify-apt.sh index c5bd4818c2..0f6f935b9e 100755 --- a/dev/release/verify-apt.sh +++ b/dev/release/verify-apt.sh @@ -197,3 +197,11 @@ ${APT_INSTALL} ruby-dev rubygems-integration gem install gobject-introspection ruby -r gi -e "p GI.load('ADBC')" echo "::endgroup::" + +echo "::group::Test ADBC Arrow GLib" + +${APT_INSTALL} libadbc-arrow-glib-dev=${package_version} +${APT_INSTALL} libadbc-arrow-glib-doc=${package_version} + +ruby -r gi -e "p GI.load('ADBCArrow')" +echo "::endgroup::" diff --git a/dev/release/verify-yum.sh b/dev/release/verify-yum.sh index 244fed4593..f7f0236117 100755 --- a/dev/release/verify-yum.sh +++ b/dev/release/verify-yum.sh @@ -157,7 +157,7 @@ echo "::group::Test ADBC Snowflake Driver" ${install_command} --enablerepo=epel adbc-driver-snowflake-devel-${package_version} echo "::endgroup::" -echo "::group::Test Apache Arrow GLib" +echo "::group::Test ADBC GLib" export G_DEBUG=fatal-warnings ${install_command} --enablerepo=epel adbc-glib-devel-${package_version} @@ -167,3 +167,11 @@ ${install_command} "${ruby_devel_packages[@]}" gem install gobject-introspection ruby -r gi -e "p GI.load('ADBC')" echo "::endgroup::" + +echo "::group::Test ADBC Arrow GLib" + +${install_command} --enablerepo=epel adbc-arrow-glib-devel-${package_version} +${install_command} --enablerepo=epel adbc-arrow-glib-doc-${package_version} + +ruby -r gi -e "p GI.load('ADBCArrow')" +echo "::endgroup::" diff --git a/glib/adbc-arrow-glib/adbc-arrow-glib.h b/glib/adbc-arrow-glib/adbc-arrow-glib.h new file mode 100644 index 0000000000..d9b485f300 --- /dev/null +++ b/glib/adbc-arrow-glib/adbc-arrow-glib.h @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 + +#include diff --git a/glib/adbc-arrow-glib/meson.build b/glib/adbc-arrow-glib/meson.build new file mode 100644 index 0000000000..65103693d5 --- /dev/null +++ b/glib/adbc-arrow-glib/meson.build @@ -0,0 +1,115 @@ +# -*- indent-tabs-mode: nil -*- +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +sources = files( + 'statement.c', +) + +definition_headers = files( + 'statement.h', +) + +headers = definition_headers +headers += files( + 'adbc-arrow-glib.h', +) + +version_h_conf = configuration_data() +version_h_conf.set('GADBC_ARROW_VERSION', meson.project_version()) +version_h_conf.set('GADBC_ARROW_VERSION_MAJOR', version_major) +version_h_conf.set('GADBC_ARROW_VERSION_MINOR', version_minor) +version_h_conf.set('GADBC_ARROW_VERSION_MICRO', version_micro) +version_h = configure_file(input: 'version.h.in', + output: 'version.h', + configuration: version_h_conf) +headers += version_h + +enums = gnome.mkenums_simple('enum-types', + identifier_prefix: 'GADBCArrow', + sources: definition_headers, + symbol_prefix: 'gadbc_arrow') +enums_header = enums[1] + +install_headers(headers, subdir: 'adbc-arrow-glib') + + +dependencies = [ + adbc_glib, + arrow_glib, +] +libadbc_arrow_glib = library('adbc-arrow-glib', + c_args: '-DG_LOG_DOMAIN="ADBC-Arrow"', + sources: sources + enums, + install: true, + dependencies: dependencies, + include_directories: base_include_directories, + soversion: so_version, + version: library_version) +adbc_arrow_glib = \ + declare_dependency(link_with: libadbc_arrow_glib, + include_directories: base_include_directories, + dependencies: dependencies, + sources: enums_header) + +pkgconfig.generate(libadbc_arrow_glib, + description: 'Arrow GLib integration API for ADBC GLib', + filebase: 'adbc-arrow-glib', + name: 'ADBC Arrow GLib', + requires: ['adbc-glib', 'arrow-glib'], + variables: pkgconfig_variables, + version: meson.project_version()) + +adbc_arrow_glib_gir = \ + gnome.generate_gir(libadbc_arrow_glib, + dependencies: [ + declare_dependency(sources: adbc_glib_gir), + arrow_glib, + ], + export_packages: 'adbc-arrow-glib', + extra_args: [ + '--warn-all', + ], + fatal_warnings: gi_fatal_warnings, + header: 'adbc-arrow-glib/adbc-arrow-glib.h', + identifier_prefix: 'GADBCArrow', + includes: [ + 'ADBC-1.0', + 'Arrow-1.0', + ], + install: true, + namespace: 'ADBCArrow', + nsversion: api_version, + sources: sources + definition_headers + enums, + symbol_prefix: 'gadbc_arrow') +if generate_vapi + adbc_arrow_glib_vapi = \ + gnome.generate_vapi('adbc-arrow-glib', + gir_dirs: [ + arrow_glib.get_variable('girdir'), + ], + install: true, + packages: [ + adbc_glib_vapi, + 'arrow-glib', + ], + sources: [adbc_arrow_glib_gir[0]], + vapi_dirs: [ + arrow_glib.get_variable('vapidir'), + ]) +endif diff --git a/glib/adbc-arrow-glib/statement.c b/glib/adbc-arrow-glib/statement.c new file mode 100644 index 0000000000..8f9352f87a --- /dev/null +++ b/glib/adbc-arrow-glib/statement.c @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 + +/** + * SECTION: statement + * @title: GADBCArrowStatement + * @include: adbc-arrow-glib/adbc-arrow-glib.h + * + * #GADBCArrowStatement is a class for Arrow GLib integrated + statement. + */ + +G_DEFINE_TYPE(GADBCArrowStatement, gadbc_arrow_statement, GADBC_TYPE_STATEMENT) + +static void gadbc_arrow_statement_init(GADBCArrowStatement* statement) {} + +static void gadbc_arrow_statement_class_init(GADBCArrowStatementClass* klass) {} + +/** + * gadbc_arrow_statement_new: + * @connection: A #GADBCConnection. + * @error: (nullable): Return location for a #GError or %NULL. + * + * Returns: A newly created #GADBCArrowStatement for @connection on + * success, %NULL otherwise. + * + * Since: 0.10.0 + */ +GADBCArrowStatement* gadbc_arrow_statement_new(GADBCConnection* connection, + GError** error) { + GADBCArrowStatement* statement = g_object_new(GADBC_ARROW_TYPE_STATEMENT, NULL); + if (gadbc_statement_initialize(GADBC_STATEMENT(statement), connection, + "[adbc-arrow][statement][new]", error)) { + return statement; + } else { + g_object_unref(statement); + return NULL; + } +} + +/** + * gadbc_arrow_statement_bind: + * @statement: A #GADBCArrowStatement. + * @record_batch: A #GArrowRecordBatch. + * @error: (out) (optional): Return location for a #GError or %NULL. + * + * Bind Arrow data. This can be used for bulk inserts or prepared + * statements. + * + * Returns: %TRUE if binding is done successfully, %FALSE + * otherwise. + * + * Since: 0.10.0 + */ +gboolean gadbc_arrow_statement_bind(GADBCArrowStatement* statement, + GArrowRecordBatch* record_batch, GError** error) { + gpointer c_abi_array = NULL; + gpointer c_abi_schema = NULL; + if (!garrow_record_batch_export(record_batch, &c_abi_array, &c_abi_schema, error)) { + return FALSE; + } + gboolean success = + gadbc_statement_bind(GADBC_STATEMENT(statement), c_abi_array, c_abi_schema, error); + g_free(c_abi_array); + g_free(c_abi_schema); + return success; +} + +/** + * gadbc_arrow_statement_bind_stream: + * @statement: A #GADBCArrowStatement. + * @reader: A #GArrowRecordBatchReader. + * @error: (out) (optional): Return location for a #GError or %NULL. + * + * Bind Arrow data stream. This can be used for bulk inserts or prepared + * statements. + * + * Returns: %TRUE if binding is done successfully, %FALSE + * otherwise. + * + * Since: 0.10.0 + */ +gboolean gadbc_arrow_statement_bind_stream(GADBCArrowStatement* statement, + GArrowRecordBatchReader* reader, + GError** error) { + gpointer c_abi_array_stream = garrow_record_batch_reader_export(reader, error); + if (!c_abi_array_stream) { + return FALSE; + } + gboolean success = + gadbc_statement_bind_stream(GADBC_STATEMENT(statement), c_abi_array_stream, error); + g_free(c_abi_array_stream); + return success; +} + +/** + * gadbc_arrow_statement_execute: + * @statement: A #GADBCStatement. + * @need_result: Whether the results are received by @reader or not. + * @reader: (out) (optional): Return location for the execution. + * @n_rows_affected: (out) (optional): Return location for the number of rows + * affected if known. + * @error: (out) (optional): Return location for a #GError or %NULL. + * + * Execute a statement and get the results. + * + * This invalidates any prior result sets. + * + * Returns: %TRUE if execution is done successfully, %FALSE otherwise. + * + * Since: 0.10.0 + */ +gboolean gadbc_arrow_statement_execute(GADBCArrowStatement* statement, + gboolean need_result, + GArrowRecordBatchReader** reader, + gint64* n_rows_affected, GError** error) { + gpointer c_abi_array_stream = NULL; + if (!gadbc_statement_execute(GADBC_STATEMENT(statement), need_result, + reader ? &c_abi_array_stream : NULL, n_rows_affected, + error)) { + return FALSE; + } + if (need_result && reader) { + *reader = garrow_record_batch_reader_import(c_abi_array_stream, error); + g_free(c_abi_array_stream); + } + return TRUE; +} diff --git a/glib/adbc-arrow-glib/statement.h b/glib/adbc-arrow-glib/statement.h new file mode 100644 index 0000000000..2aaaa9e6b4 --- /dev/null +++ b/glib/adbc-arrow-glib/statement.h @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 +#include + +#include + +G_BEGIN_DECLS + +#define GADBC_ARROW_TYPE_STATEMENT (gadbc_arrow_statement_get_type()) +G_DECLARE_DERIVABLE_TYPE(GADBCArrowStatement, gadbc_arrow_statement, GADBCArrow, + STATEMENT, GADBCStatement) +struct _GADBCArrowStatementClass { + GADBCStatementClass parent_class; +}; + +GADBC_ARROW_AVAILABLE_IN_0_10 +GADBCArrowStatement* gadbc_arrow_statement_new(GADBCConnection* connection, + GError** error); +GADBC_AVAILABLE_IN_0_10 +gboolean gadbc_arrow_statement_bind(GADBCArrowStatement* statement, + GArrowRecordBatch* record_batch, GError** error); +GADBC_AVAILABLE_IN_0_10 +gboolean gadbc_arrow_statement_bind_stream(GADBCArrowStatement* statement, + GArrowRecordBatchReader* reader, + GError** error); +GADBC_AVAILABLE_IN_0_10 +gboolean gadbc_arrow_statement_execute(GADBCArrowStatement* statement, + gboolean need_result, + GArrowRecordBatchReader** reader, + gint64* n_rows_affected, GError** error); + +G_END_DECLS diff --git a/glib/adbc-arrow-glib/version.h.in b/glib/adbc-arrow-glib/version.h.in new file mode 100644 index 0000000000..6fd0068839 --- /dev/null +++ b/glib/adbc-arrow-glib/version.h.in @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 + +/** + * SECTION: version + * @section_id: version-macros + * @title: Version related macros + * @include: adbc-arrow-glib/adbc-arrow-glib.h + * + * ADBC Arrow GLib provides macros that can be used by C pre-processor. + * They are useful to check version related things at compile time. + */ + +/** + * GADBC_ARROW_VERSION_MAJOR: + * + * The major version. + * + * Since: 0.10.0 + */ +#define GADBC_ARROW_VERSION_MAJOR (@GADBC_ARROW_VERSION_MAJOR@) + +/** + * GADBC_ARROW_VERSION_MINOR: + * + * The minor version. + * + * Since: 0.10.0 + */ +#define GADBC_ARROW_VERSION_MINOR (@GADBC_ARROW_VERSION_MINOR@) + +/** + * GADBC_ARROW_VERSION_MICRO: + * + * The micro version. + * + * Since: 0.10.0 + */ +#define GADBC_ARROW_VERSION_MICRO (@GADBC_ARROW_VERSION_MICRO@) + +/** + * GADBC_ARROW_VERSION_CHECK: + * @major: A major version to check for. + * @minor: A minor version to check for. + * @micro: A micro version to check for. + * + * You can use this macro in C pre-processor. + * + * Returns: %TRUE if the compile time ADBC Arrow GLib version is the + * same as or newer than the passed version, %FALSE otherwise. + * + * Since: 0.10.0 + */ +#define GADBC_ARROW_VERSION_CHECK(major, minor, micro) \ + (GADBC_ARROW_VERSION_MAJOR > (major) || \ + (GADBC_ARROW_VERSION_MAJOR == (major) && \ + GADBC_ARROW_VERSION_MINOR > (minor)) || \ + (GADBC_ARROW_VERSION_MAJOR == (major) && \ + GADBC_ARROW_VERSION_MINOR == (minor) && \ + GADBC_ARROW_VERSION_MICRO >= (micro))) + +/** + * GADBC_ARROW_DISABLE_DEPRECATION_WARNINGS: + * + * If this macro is defined, no deprecated warnings are produced. + * + * You must define this macro before including the + * adbc-arrow-glib/adbc-arrow-glib.h header. + * + * Since: 0.10.0 + */ + +#ifdef GADBC_ARROW_DISABLE_DEPRECATION_WARNINGS +# define GADBC_ARROW_DEPRECATED +# define GADBC_ARROW_DEPRECATED_FOR(function) +# define GADBC_ARROW_UNAVAILABLE(major, minor) +#else +# define GADBC_ARROW_DEPRECATED G_DEPRECATED +# define GADBC_ARROW_DEPRECATED_FOR(function) G_DEPRECATED_FOR(function) +# define GADBC_ARROW_UNAVAILABLE(major, minor) G_UNAVAILABLE(major, minor) +#endif + +/** + * GADBC_ARROW_VERSION_0_10: + * + * You can use this macro value for compile time API version check. + * + * Since: 0.10.0 + */ +#define GADBC_ARROW_VERSION_0_10 G_ENCODE_VERSION(0, 10) + +/** + * GADBC_ARROW_VERSION_MIN_REQUIRED: + * + * You can use this macro for compile time API version check. + * + * This macro value must be one of the predefined version macros such + * as %GADBC_ARROW_VERSION_0_10. + * + * If you use any functions that is defined by newer version than + * %GADBC_ARROW_VERSION_MIN_REQUIRED, deprecated warnings are produced at + * compile time. + * + * You must define this macro before including the + * adbc-glib/adbc-glib.h header. + * + * Since: 0.10.0 + */ +#ifndef GADBC_ARROW_VERSION_MIN_REQUIRED +# define GADBC_ARROW_VERSION_MIN_REQUIRED \ + G_ENCODE_VERSION(GADBC_ARROW_VERSION_MAJOR, GADBC_ARROW_VERSION_MINOR) +#endif + +/** + * GADBC_ARROW_VERSION_MAX_ALLOWED: + * + * You can use this macro for compile time API version check. + * + * This macro value must be one of the predefined version macros such + * as %GADBC_ARROW_VERSION_0_10. + * + * If you use any functions that is defined by newer version than + * %GADBC_ARROW_VERSION_MAX_ALLOWED, deprecated warnings are produced at + * compile time. + * + * You must define this macro before including the + * adbc-arrow-glib/adbc-arrow-glib.h header. + * + * Since: 0.10.0 + */ +#ifndef GADBC_ARROW_VERSION_MAX_ALLOWED +# define GADBC_ARROW_VERSION_MAX_ALLOWED \ + G_ENCODE_VERSION(GADBC_ARROW_VERSION_MAJOR, GADBC_ARROW_VERSION_MINOR) +#endif + + +#define GADBC_ARROW_AVAILABLE_IN_ALL + +#if GADBC_ARROW_VERSION_MIN_REQUIRED >= GADBC_ARROW_VERSION_0_10 +# define GADBC_ARROW_DEPRECATED_IN_0_10 GADBC_ARROW_DEPRECATED +# define GADBC_ARROW_DEPRECATED_IN_0_10_FOR(function) GADBC_ARROW_DEPRECATED_FOR(function) +#else +# define GADBC_ARROW_DEPRECATED_IN_0_10 +# define GADBC_ARROW_DEPRECATED_IN_0_10_FOR(function) +#endif + +#if GADBC_ARROW_VERSION_MAX_ALLOWED < GADBC_ARROW_VERSION_0_10 +# define GADBC_ARROW_AVAILABLE_IN_0_10 GADBC_ARROW_UNAVAILABLE(0, 10) +#else +# define GADBC_ARROW_AVAILABLE_IN_0_10 +#endif diff --git a/glib/adbc-glib/statement.c b/glib/adbc-glib/statement.c index 36734a692f..cb17eb3c12 100644 --- a/glib/adbc-glib/statement.c +++ b/glib/adbc-glib/statement.c @@ -65,35 +65,62 @@ static void gadbc_statement_class_init(GADBCStatementClass* klass) { } /** - * gadbc_statement_new: + * gadbc_statement_initialize: (skip) + * @statement: A #GADBCStatement. * @connection: A #GADBCConnection. + * @context: A context for error message. * @error: (nullable): Return location for a #GError or %NULL. * - * Returns: A newly created #GADBCStatement for @connection on success, - * %NULL otherwise. + * This is only for implementing subclass of #GADBCStatement. In + * general, users should use gadbc_statement_new(). * - * Since: 0.1.0 + * Initializes an empty #GADBCStatement with the given + * #GADBCConnection. + * + * Returns: %TRUE if initialization is done successfully, %FALSE otherwise. + * + * Since: 0.10.0 */ -GADBCStatement* gadbc_statement_new(GADBCConnection* connection, GError** error) { - const gchar* context = "[adbc][statement][new]"; +gboolean gadbc_statement_initialize(GADBCStatement* statement, + GADBCConnection* connection, const char* context, + GError** error) { struct AdbcConnection* adbc_connection = gadbc_connection_get_raw(connection, context, error); if (!adbc_connection) { - return NULL; + return FALSE; } - GADBCStatement* statement = g_object_new(GADBC_TYPE_STATEMENT, NULL); GADBCStatementPrivate* priv = gadbc_statement_get_instance_private(statement); struct AdbcError adbc_error = {}; AdbcStatusCode status_code = AdbcStatementNew(adbc_connection, &(priv->adbc_statement), &adbc_error); priv->initialized = gadbc_error_check(error, status_code, &adbc_error, context); if (!priv->initialized) { - g_object_unref(statement); - return NULL; + return FALSE; } priv->connection = connection; g_object_ref(priv->connection); - return statement; + return TRUE; +} + +/** + * gadbc_statement_new: + * @connection: A #GADBCConnection. + * @error: (nullable): Return location for a #GError or %NULL. + * + * Returns: A newly created #GADBCStatement for @connection on success, + * %NULL otherwise. + * + * Since: 0.1.0 + */ +GADBCStatement* gadbc_statement_new(GADBCConnection* connection, GError** error) { + GADBCStatement* statement = g_object_new(GADBC_TYPE_STATEMENT, NULL); + if (gadbc_statement_initialize(statement, connection, "[adbc][statement][new]", + error)) { + return statement; + } else { + g_object_unref(statement); + return NULL; + } } /** diff --git a/glib/adbc-glib/statement.h b/glib/adbc-glib/statement.h index cf6a3d5b98..07f6ade87c 100644 --- a/glib/adbc-glib/statement.h +++ b/glib/adbc-glib/statement.h @@ -47,6 +47,10 @@ struct _GADBCStatementClass { GObjectClass parent_class; }; +GADBC_AVAILABLE_IN_0_10 +gboolean gadbc_statement_initialize(GADBCStatement* statement, + GADBCConnection* connection, const gchar* context, + GError** error); GADBC_AVAILABLE_IN_0_1 GADBCStatement* gadbc_statement_new(GADBCConnection* connection, GError** error); GADBC_AVAILABLE_IN_0_1 diff --git a/glib/adbc-glib/version.h.in b/glib/adbc-glib/version.h.in index bf75cfc436..a7a8837970 100644 --- a/glib/adbc-glib/version.h.in +++ b/glib/adbc-glib/version.h.in @@ -100,6 +100,15 @@ # define GADBC_UNAVAILABLE(major, minor) G_UNAVAILABLE(major, minor) #endif +/** + * GADBC_VERSION_0_10: + * + * You can use this macro value for compile time API version check. + * + * Since: 0.10.0 + */ +#define GADBC_VERSION_0_10 G_ENCODE_VERSION(0, 10) + /** * GADBC_VERSION_0_4: * @@ -165,6 +174,20 @@ #define GADBC_AVAILABLE_IN_ALL +#if GADBC_VERSION_MIN_REQUIRED >= GADBC_VERSION_0_10 +# define GADBC_DEPRECATED_IN_0_10 GADBC_DEPRECATED +# define GADBC_DEPRECATED_IN_0_10_FOR(function) GADBC_DEPRECATED_FOR(function) +#else +# define GADBC_DEPRECATED_IN_0_10 +# define GADBC_DEPRECATED_IN_0_10_FOR(function) +#endif + +#if GADBC_VERSION_MAX_ALLOWED < GADBC_VERSION_0_10 +# define GADBC_AVAILABLE_IN_0_10 GADBC_UNAVAILABLE(0, 10) +#else +# define GADBC_AVAILABLE_IN_0_10 +#endif + #if GADBC_VERSION_MIN_REQUIRED >= GADBC_VERSION_0_4 # define GADBC_DEPRECATED_IN_0_4 GADBC_DEPRECATED # define GADBC_DEPRECATED_IN_0_4_FOR(function) GADBC_DEPRECATED_FOR(function) diff --git a/glib/example/vala/meson.build b/glib/example/vala/meson.build index 3486a8c9e9..26022bcce6 100644 --- a/glib/example/vala/meson.build +++ b/glib/example/vala/meson.build @@ -25,6 +25,7 @@ if build_example and generate_vapi ], 'dependencies': [ adbc_glib_vapi, + adbc_arrow_glib_vapi, arrow_glib, dependency('gobject-2.0'), ], @@ -43,6 +44,6 @@ files = [ ] install_data(files, install_dir: join_paths(data_dir, - meson.project_name(), + 'adbc-arrow-glib', 'example', 'vala')) diff --git a/glib/example/vala/sqlite.vala b/glib/example/vala/sqlite.vala index 76183539dc..c184bb5138 100644 --- a/glib/example/vala/sqlite.vala +++ b/glib/example/vala/sqlite.vala @@ -27,20 +27,15 @@ int main (string[] args) { var connection = new GADBC.Connection (); connection.init (database); try { - var statement = new GADBC.Statement (connection); + var statement = new GADBCArrow.Statement (connection); string sql = "SELECT sqlite_version() AS version"; statement.set_sql_query (sql); try { - void *c_abi_array_stream = null; + GArrow.RecordBatchReader reader; int64 n_rows_affected; - statement.execute (true, out c_abi_array_stream, out n_rows_affected); - try { - var reader = GArrow.RecordBatchReader.import (c_abi_array_stream); - var table = reader.read_all (); - stdout.printf ("Result:\n%s", table.to_string ()); - } finally { - GLib.free (c_abi_array_stream); - } + statement.execute (true, out reader, out n_rows_affected); + var table = reader.read_all (); + stdout.printf ("Result:\n%s", table.to_string ()); exit_code = Posix.EXIT_SUCCESS; } catch (GLib.Error error) { GLib.error ("Failed to execute a statement: %s", error.message); diff --git a/glib/meson.build b/glib/meson.build index f95563f29d..dca660945e 100644 --- a/glib/meson.build +++ b/glib/meson.build @@ -78,11 +78,20 @@ if generate_vapi endif subdir('adbc-glib') +arrow_glib = dependency('arrow-glib', required: generate_vapi) +if arrow_glib.found() + subdir('adbc-arrow-glib') +endif subdir('example') install_data('../LICENSE.txt', 'README.md', install_dir: data_dir / 'doc' / meson.project_name()) +if arrow_glib.found() + install_data('../LICENSE.txt', + 'README.md', + install_dir: data_dir / 'doc' / 'adbc-arrow-glib') +endif ruby = find_program('ruby', required: false) if ruby.found() diff --git a/glib/test/run.rb b/glib/test/run.rb index 352c34faf1..2685a1ad60 100755 --- a/glib/test/run.rb +++ b/glib/test/run.rb @@ -30,6 +30,11 @@ require "gi" ADBC = GI.load("ADBC") +begin + ADBCArrow = GI.load("ADBCArrow") +rescue GObjectIntrospection::RepositoryError => error + puts("ADBCArrow isn't found: #{error}") +end require_relative "helper" diff --git a/glib/test/run.sh b/glib/test/run.sh index 96fd62613c..7a6dfc4723 100755 --- a/glib/test/run.sh +++ b/glib/test/run.sh @@ -22,6 +22,7 @@ build_dir="$(cd .; pwd)" modules=( adbc-glib + adbc-arrow-glib ) for module in "${modules[@]}"; do diff --git a/glib/test/test-arrow-statement.rb b/glib/test/test-arrow-statement.rb new file mode 100644 index 0000000000..97f9807f38 --- /dev/null +++ b/glib/test/test-arrow-statement.rb @@ -0,0 +1,80 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +class ArrowStatementTest < Test::Unit::TestCase + include Helper + + def setup + omit("adbc-arrow-glib isn't built") unless defined?(ADBCArrow) + + @database = ADBC::Database.new + @database.set_option("driver", "adbc_driver_sqlite") + @database.set_option("uri", ":memory:") + @database.init + @connection = ADBC::Connection.new + @connection.init(@database) + @statement = ADBCArrow::Statement.new(@connection) + end + + def teardown + @statement&.release + end + + def test_execute + @statement.set_sql_query("SELECT 1") + _, reader, _ = @statement.execute(true) + assert_equal(Arrow::Table.new("1" => Arrow::Int64Array.new([1])), + reader.read_all) + end + + def test_bind + @statement.set_sql_query("CREATE TABLE data (number int)") + @statement.execute(false) + + record_batch = + Arrow::RecordBatch.new(number: Arrow::Int64Array.new([10, 20, 30])) + @statement.ingest_target_table = "data" + @statement.ingest_mode = :append + @statement.bind(record_batch) + _, _, n_rows_affected = @statement.execute(false) + assert_equal(3, n_rows_affected) + + @statement.set_sql_query("SELECT * FROM data") + _, reader, _ = @statement.execute(true) + assert_equal(record_batch.to_table, + reader.read_all) + end + + def test_bind_stream + @statement.set_sql_query("CREATE TABLE data (number int)") + @statement.execute(false) + + record_batch = + Arrow::RecordBatch.new(number: Arrow::Int64Array.new([10, 20, 30])) + @statement.ingest_target_table = "data" + @statement.ingest_mode = :append + reader = Arrow::RecordBatchReader.new([record_batch]) + @statement.bind_stream(reader) + _, _, n_rows_affected = @statement.execute(false) + assert_equal(3, n_rows_affected) + + @statement.set_sql_query("SELECT * FROM data") + _, reader, _ = @statement.execute(true) + assert_equal(record_batch.to_table, + reader.read_all) + end +end diff --git a/glib/test/test-statement.rb b/glib/test/test-statement.rb index b1b72daeca..9f565158f0 100644 --- a/glib/test/test-statement.rb +++ b/glib/test/test-statement.rb @@ -46,7 +46,6 @@ def test_bind record_batch = Arrow::RecordBatch.new(number: Arrow::Int64Array.new([10, 20, 30])) - @statement.set_sql_query("INSERT INTO data VALUES (?)") @statement.ingest_target_table = "data" @statement.ingest_mode = :append _, c_abi_array, c_abi_schema = record_batch.export @@ -76,7 +75,6 @@ def test_bind_stream record_batch = Arrow::RecordBatch.new(number: Arrow::Int64Array.new([10, 20, 30])) - @statement.set_sql_query("INSERT INTO data VALUES (?)") @statement.ingest_target_table = "data" @statement.ingest_mode = :append reader = Arrow::RecordBatchReader.new([record_batch]) diff --git a/ruby/dependency-check/Rakefile b/ruby/dependency-check/Rakefile index 05ae3ee742..a083e09cbe 100644 --- a/ruby/dependency-check/Rakefile +++ b/ruby/dependency-check/Rakefile @@ -34,12 +34,12 @@ end namespace :dependency do desc "Check dependency" task :check do - unless PKGConfig.check_version?("adbc-glib", + unless PKGConfig.check_version?("adbc-arrow-glib", ADBC::Version::MAJOR, ADBC::Version::MINOR, ADBC::Version::MICRO) - unless NativePackageInstaller.install(debian: "libadbc-glib-dev", - redhat: "adbc-glib-devel") + unless NativePackageInstaller.install(debian: "libadbc-arrow-glib-dev", + redhat: "adbc-arrow-glib-devel") exit(false) end end diff --git a/ruby/lib/adbc.rb b/ruby/lib/adbc.rb index 5dfe18f7db..f2482bfb5a 100644 --- a/ruby/lib/adbc.rb +++ b/ruby/lib/adbc.rb @@ -24,6 +24,16 @@ module ADBC class Error < StandardError end +end - Loader.load +ADBC::Loader.load +begin + ADBCArrow::Loader.load +rescue GObjectIntrospection::RepositoryError +else + module ADBC + RawStatement = Statement + remove_const(:Statement) + Statement = ADBCArrow::Statement + end end diff --git a/ruby/lib/adbc/arrow-statement.rb b/ruby/lib/adbc/arrow-statement.rb new file mode 100644 index 0000000000..821ca637dc --- /dev/null +++ b/ruby/lib/adbc/arrow-statement.rb @@ -0,0 +1,65 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +module ADBCArrow + class Statement + extend ADBC::StatementOpenable + include ADBC::StatementOperations + + alias_method :execute_raw, :execute + def execute(need_result: true) + _, reader, n_rows_affected = execute_raw(need_result) + if need_result + begin + if block_given? + yield(reader, n_rows_affected) + else + [reader.read_all, n_rows_affected] + end + end + else + if block_given? + yield(n_rows_affected) + else + n_rows_affected + end + end + end + + alias_method :bind_raw, :bind + def bind(*args) + n_args = args.size + if block_given? + message = "wrong number of arguments (given #{n_args}, expected 1 with block)" + raise ArgumentError, message unless n_args == 1 + values = args[0] + if values.is_a?(Arrow::Table) + values = Arrow::TableBatchReader.new(values) + end + if values.is_a?(Arrow::RecordBatchReader) + bind_stream(values) + yield + else + bind_raw(values) + yield + end + else + bind_raw(*args) + end + end + end +end diff --git a/ruby/lib/adbc/loader.rb b/ruby/lib/adbc/loader.rb index db776cf210..0e6468b2d1 100644 --- a/ruby/lib/adbc/loader.rb +++ b/ruby/lib/adbc/loader.rb @@ -43,3 +43,22 @@ def load_function_info_singleton_method(info, klass, method_name) end end end + +module ADBCArrow + class Loader < GObjectIntrospection::Loader + class << self + def load + super("ADBCArrow", ADBCArrow) + end + end + + private + def post_load(repository, namespace) + require_libraries + end + + def require_libraries + require_relative "arrow-statement" + end + end +end diff --git a/ruby/lib/adbc/statement-openable.rb b/ruby/lib/adbc/statement-openable.rb new file mode 100644 index 0000000000..b805b33d7d --- /dev/null +++ b/ruby/lib/adbc/statement-openable.rb @@ -0,0 +1,33 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +module ADBC + module StatementOpenable + def open(connection) + statement = new(connection) + if block_given? + begin + yield(statement) + ensure + statement.release + end + else + statement + end + end + end +end diff --git a/ruby/lib/adbc/statement-operations.rb b/ruby/lib/adbc/statement-operations.rb new file mode 100644 index 0000000000..79dd106b77 --- /dev/null +++ b/ruby/lib/adbc/statement-operations.rb @@ -0,0 +1,33 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +module ADBC + module StatementOperations + def ingest(table_name, values, mode: :create) + self.ingest_target_table = table_name + self.ingest_mode = mode + bind(values) do + execute(need_result: false) + end + end + + def query(sql, &block) + self.sql_query = sql + execute(&block) + end + end +end diff --git a/ruby/lib/adbc/statement.rb b/ruby/lib/adbc/statement.rb index d89ea0d044..f093be48bc 100644 --- a/ruby/lib/adbc/statement.rb +++ b/ruby/lib/adbc/statement.rb @@ -15,22 +15,13 @@ # specific language governing permissions and limitations # under the License. +require_relative "statement-openable" +require_relative "statement-operations" + module ADBC class Statement - class << self - def open(connection) - statement = new(connection) - if block_given? - begin - yield(statement) - ensure - statement.release - end - else - statement - end - end - end + extend StatementOpenable + include StatementOperations alias_method :execute_raw, :execute def execute(need_result: true) @@ -94,25 +85,5 @@ def bind(*args) bind_raw(*args) end end - - def ingest(table_name, values, mode: :create) - insert = "INSERT INTO #{table_name} (" # TODO escape - fields = values.schema.fields - insert << fields.collect(&:name).join(", ") - insert << ") VALUES (" - insert << (["?"] * fields.size).join(", ") - insert << ")" - self.sql_query = insert - self.ingest_target_table = table_name - self.ingest_mode = mode - bind(values) do - execute(need_result: false) - end - end - - def query(sql, &block) - self.sql_query = sql - execute(&block) - end end end