chdb java sdk 的设计简单说明
chdb java sdk 是基于了jni 以及chdb c library 开发的,玩法上可以学习下
参考玩法
- 基于cmake 进行项目构建
对于jni 头文件的引用,chdb 直接复制到了项目中
- jni native 方法只有一个
ChdbJniUtil.java 中暴露的
public static native LocalResultV2 executeQuery(String query);
native 实现, 内部调用了不少chdb c library 的方法,核心是通过queryToBuffer 获取数据,然后转换为java 数据类型
JNIEXPORT jobject JNICALL Java_org_chdb_jdbc_ChdbJniUtil_executeQuery(JNIEnv *env, jclass clazz, jstring query) {
// 1. Convert Java String to C++ string
std::cout << "call func: ChdbJniUtil_executeQuery!" << std::endl;
const char *queryStr = env->GetStringUTFChars(query, nullptr);
if (queryStr == nullptr) {
std::cerr << "Error: Failed to convert Java string to C++ string" << std::endl;
return nullptr;
}
// 2. Call the native query function
local_result_v2 *result = queryToBuffer(queryStr);
// 3. Release the Java string resources
env->ReleaseStringUTFChars(query, queryStr);
// 4. Check if the result is null (indicates an error)
if (result == nullptr) {
std::cerr << "Error: result is null" << std::endl;
return nullptr;
}
// 5. Find the Java class and its constructor
jclass resultClass = env->FindClass("org/chdb/jdbc/LocalResultV2");
if (resultClass == nullptr) {
std::cerr << "Error: resultClass is null" << std::endl;
free_result_v2(result); // Ensure to free the result even on error
return nullptr;
}
jmethodID constructor = env->GetMethodID(resultClass, "<init>", "(Ljava/nio/ByteBuffer;JJDLjava/lang/String;)V");
if (constructor == nullptr) {
std::cerr << "Error: constructor is null" << std::endl;
free_result_v2(result); // Ensure to free the result even on error
return nullptr;
}
// 6. Create a direct ByteBuffer for the result buffer
jobject buffer = env->NewDirectByteBuffer(result->buf, result->len);
if (buffer == nullptr) {
std::cerr << "Error: Failed to create ByteBuffer" << std::endl;
free_result_v2(result);
return nullptr;
}
// 7. Create the Java String for the error message, if present
jstring errorMessage = result->error_message ? env->NewStringUTF(result->error_message) : nullptr;
// 8. Create a new Java object to hold the result
jobject resultObj = env->NewObject(resultClass, constructor, buffer, result->rows_read, result->bytes_read, result->elapsed, errorMessage);
if (resultObj == nullptr) {
std::cerr << "Error: Failed to create result object" << std::endl;
free_result_v2(result);
return nullptr;
}
// 9. Free the native result structure
free_result_v2(result);
// 10. Return the Java object
return resultObj;
}
- executeQuery 的使用
主要在标准Statement 实现类ChdbStatement 的executeQuery 中
@Override
public ResultSet executeQuery(String sql) throws SQLException {
LocalResultV2 result = ChdbJniUtil.executeQuery(sql);
System.out.println("sql: " + sql);
try {
return new ChdbResultSet(result);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
说明
chdb java sdk 属于一个比较标准的jni 玩法,但是机制上不如duckdb 的java sdk 开发规范,chdb 基于了c,但是duckdb 基于了c++
参考资料
https://github.com/chdb-io/chdb-java
https://github.com/duckdb/duckdb-java
https://github.com/duckdb/duckdb-java/blob/main/src/jni/duckdb_java.cpp