快速入门¶
食谱来源:quickstart.cc
我们将简要介绍使用 C++17 中的 SQLite 驱动程序的 ADBC 基本功能。
安装¶
本快速入门实际上是一个可读的 C++ 文件。您可以克隆存储库,构建示例并遵循操作步骤。
我们假设您使用的是 conda-forge 来管理依赖项。CMake、C++17 编译器和 ADBC 库是必需的。它们可以按如下方式安装
mamba install cmake compilers libadbc-driver-manager libadbc-driver-sqlite
构建¶
我们将在这里使用 CMake。从 ADBC 存储库的源代码检出开始
mkdir build
cd build
cmake ../docs/source/cpp/recipe
cmake --build . --target quickstart
./quickstart
使用 ADBC¶
让我们从一些包含文件开始
59// For EXIT_SUCCESS
60#include <cstdlib>
61// For strerror
62#include <cstring>
63#include <iostream>
64
65#include <arrow-adbc/adbc.h>
66#include <nanoarrow.h>
然后我们将添加一些(非常基本的)错误检查帮助程序。
70// Error-checking helper for ADBC calls.
71// Assumes that there is an AdbcError named `error` in scope.
72#define CHECK_ADBC(EXPR) \
73 if (AdbcStatusCode status = (EXPR); status != ADBC_STATUS_OK) { \
74 if (error.message != nullptr) { \
75 std::cerr << error.message << std::endl; \
76 } \
77 return EXIT_FAILURE; \
78 }
79
80// Error-checking helper for ArrowArrayStream.
81#define CHECK_STREAM(STREAM, EXPR) \
82 if (int status = (EXPR); status != 0) { \
83 std::cerr << "(" << std::strerror(status) << "): "; \
84 const char* message = (STREAM).get_last_error(&(STREAM)); \
85 if (message != nullptr) { \
86 std::cerr << message << std::endl; \
87 } else { \
88 std::cerr << "(no error message)" << std::endl; \
89 } \
90 return EXIT_FAILURE; \
91 }
92
93// Error-checking helper for Nanoarrow.
94#define CHECK_NANOARROW(EXPR) \
95 if (int status = (EXPR); status != 0) { \
96 std::cerr << "(" << std::strerror(status) << "): failed" << std::endl; \
97 return EXIT_FAILURE; \
98 }
99
100int main() {
加载驱动程序¶
我们将使用驱动程序管理器加载 SQLite 驱动程序。我们无需以这种方式显式链接到驱动程序。
107 AdbcError error = {};
108
109 AdbcDatabase database = {};
110 CHECK_ADBC(AdbcDatabaseNew(&database, &error));
驱动程序管理器通过 driver
选项知道我们想要哪个驱动程序。
113 CHECK_ADBC(AdbcDatabaseSetOption(&database, "driver", "adbc_driver_sqlite", &error));
114 CHECK_ADBC(AdbcDatabaseInit(&database, &error));
创建连接¶
ADBC 区分“数据库”、“连接”和“语句”。“数据库”在多个连接之间共享状态。例如,在 SQLite 驱动程序中,它保存 SQLite 的实际实例。“连接”是到数据库的一个连接。
125 AdbcConnection connection = {};
126 CHECK_ADBC(AdbcConnectionNew(&connection, &error));
127 CHECK_ADBC(AdbcConnectionInit(&connection, &database, &error));
创建语句¶
语句允许我们执行查询。它们用于准备好的查询和非准备好的(“临时”)查询。
135 AdbcStatement statement = {};
136 CHECK_ADBC(AdbcStatementNew(&connection, &statement, &error));
执行查询¶
我们通过在语句上设置查询,然后调用 AdbcStatementExecuteQuery()
来执行查询。结果通过 Arrow C 数据接口 返回。
147 struct ArrowArrayStream stream = {};
148 int64_t rows_affected = -1;
149
150 CHECK_ADBC(AdbcStatementSetSqlQuery(&statement, "SELECT 42 AS THEANSWER", &error));
151 CHECK_ADBC(AdbcStatementExecuteQuery(&statement, &stream, &rows_affected, &error));
虽然 API 为我们提供了行数,但 SQLite 驱动程序实际上无法提前知道结果集中有多少行,因此该值实际上将只是 -1
来表示该值未知。
157 std::cout << "Got " << rows_affected << " rows" << std::endl;
我们需要一个 Arrow 实现来读取实际结果。我们可以使用 Arrow C++ 或 Nanoarrow 来实现。为简单起见,我们将在这里使用 Nanoarrow。(此示例的 CMake 配置从源代码下载并构建 Nanoarrow 作为构建的一部分。)
首先我们将获取数据的模式
169 ArrowSchema schema = {};
170 CHECK_STREAM(stream, stream.get_schema(&stream, &schema));
然后我们可以使用 Nanoarrow 来打印它
173 char buf[1024] = {};
174 ArrowSchemaToString(&schema, buf, sizeof(buf), /*recursive=*/1);
175 std::cout << buf << std::endl;
现在我们可以读取数据了。数据作为 Arrow 记录批处理流返回。
179 while (true) {
180 ArrowArray batch = {};
181 CHECK_STREAM(stream, stream.get_next(&stream, &batch));
182
183 if (batch.release == nullptr) {
184 // Stream has ended
185 break;
186 }
我们也可以使用 Nanoarrow 来打印数据。
189 ArrowArrayView view = {};
190 CHECK_NANOARROW(ArrowArrayViewInitFromSchema(&view, &schema, nullptr));
191 CHECK_NANOARROW(ArrowArrayViewSetArray(&view, &batch, nullptr));
192 std::cout << "Got a batch with " << batch.length << " rows" << std::endl;
193 for (int64_t i = 0; i < batch.length; i++) {
194 std::cout << "THEANSWER[" << i
195 << "] = " << view.children[0]->buffer_views[1].data.as_int64[i]
196 << std::endl;
197 }
198 ArrowArrayViewReset(&view);
199 }
200
201 std::cout << "Finished reading result set" << std::endl;
202 stream.release(&stream);
清理¶
最后,我们必须释放所有资源。
208 CHECK_ADBC(AdbcStatementRelease(&statement, &error));
209 CHECK_ADBC(AdbcConnectionRelease(&connection, &error));
210 CHECK_ADBC(AdbcDatabaseRelease(&database, &error));
211 return EXIT_SUCCESS;
212}