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

posted on 2025-08-20 08:00  荣锋亮  阅读(15)  评论(0)    收藏  举报

导航