快速入門¶
食譜來源: 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¶
讓我們先從一些包含檔開始
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}