快速入门¶
配方来源:quickstart.cc
在这里,我们将简要介绍 ADBC 在 C++17 中使用 SQLite 驱动程序的基本功能。
安装¶
此快速入门实际上是一个文学 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¶
让我们从一些 include 开始
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。)
首先,我们将获取数据的模式
170 ArrowSchema schema = {};
171 CHECK_STREAM(stream, stream.get_schema(&stream, &schema));
然后我们可以使用 Nanoarrow 打印它
174 char buf[1024] = {};
175 ArrowSchemaToString(&schema, buf, sizeof(buf), /*recursive=*/1);
176 std::cout << "Result schema: " << buf << std::endl;
现在我们可以读取数据。 数据以 Arrow 记录批处理流的形式出现。
182 while (true) {
183 ArrowArray batch = {};
184 CHECK_STREAM(stream, stream.get_next(&stream, &batch));
185
186 if (batch.release == nullptr) {
187 // Stream has ended
188 break;
189 }
我们也可以使用 Nanoarrow 打印出数据。
192 ArrowArrayView view = {};
193 CHECK_NANOARROW(ArrowArrayViewInitFromSchema(&view, &schema, nullptr));
194 CHECK_NANOARROW(ArrowArrayViewSetArray(&view, &batch, nullptr));
195 std::cout << "Got a batch with " << batch.length << " rows" << std::endl;
196 for (int64_t i = 0; i < batch.length; i++) {
197 std::cout << "THEANSWER[" << i
198 << "] = " << view.children[0]->buffer_views[1].data.as_int64[i]
199 << std::endl;
200 }
201 ArrowArrayViewReset(&view);
202 }
203 // Output:
204 // Got a batch with 1 rows
205 // THEANSWER[0] = 42
206
207 stream.release(&stream);
清理¶
最后,我们必须释放所有资源。
213 CHECK_ADBC(AdbcStatementRelease(&statement, &error));
214 CHECK_ADBC(AdbcConnectionRelease(&connection, &error));
215 CHECK_ADBC(AdbcDatabaseRelease(&database, &error));
216 return EXIT_SUCCESS;
217}
Got -1 rows
Result schema: struct<THEANSWER: int64>
Got a batch with 1 rows
THEANSWER[0] = 42