Skip to content

Commit

Permalink
Java-API implementation (#1650)
Browse files Browse the repository at this point in the history
* First example for JNI

* Java API for KuzuDatabase implemented

* KuzuConnection implemented
Skipped functions that require prepared statements.
Need to test after KuzuQueryResult is implemented.

* KuzuQueryResult implemented

* Prepared Statement implemented

* FlatTuple and DataType done
Changed binding logic for PreparedStatement
Note: the c++ implementation of FlatTuple also returns one Value at a time

* KuzuValue done
Need to review use of generics

* NodeVal implemented

* RelVal and QuerySummary done

* Added tests for Java API

* Removing extra class

* Removing commented code

* Rmove assert and refactor tests

* Using temporary directory in tests
  • Loading branch information
KasunaStony committed Jun 22, 2023
1 parent 50a1310 commit d91ca92
Show file tree
Hide file tree
Showing 27 changed files with 4,032 additions and 0 deletions.
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,23 @@ tools/nodejs_api/prebuilt/
scripts/pre-compiled-bins/headers
scripts/pre-compiled-bins/lib*
scripts/pre-compiled-bins/kuzu*

# Java API
tools/java_api/CMakeFiles/
tools/java_api/Testing/
tools/java_api/testdb/
tools/java_api/testdb/
tools/java_api_falied/
tools/test_java_api/
tools/java_api/cmake_install.cmake
tools/java_api/Notes.txt
tools/java_api/CMakeCache.txt
tools/java_api/CTestTestfile.cmake
tools/java_api/*.log
tools/java_api/*.jar
tools/java_api/*.dylib
tools/java_api/test.java
tools/java_api/*.class
tools/java_api/KuzuNative.h
tools/java_api/error.txt
tools/java_api/Makefile
58 changes: 58 additions & 0 deletions tools/java_api/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
cmake_minimum_required (VERSION 3.11)

set(CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS TRUE)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

project (kuzu_java_api)

find_package(Java REQUIRED)
find_package(JNI REQUIRED)
if (JNI_FOUND)
message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
endif()
include(UseJava)

enable_testing()

file(GLOB JAVA_SRC_FILES *.java)

set(CMAKE_JAVA_COMPILE_FLAGS -source 1.8 -target 1.8 -encoding utf-8)
add_jar(kuzu_java ${JAVA_SRC_FILES})
get_target_property(_jarFile kuzu_java JAR_FILE)
get_target_property(_classDir kuzu_java CLASSDIR)

set (_stubDir "${CMAKE_CURRENT_BINARY_DIR}")
add_custom_command(
OUTPUT KuzuNative.h
COMMAND ${Java_JAVAC_EXECUTABLE}
-h .
${JAVA_SRC_FILES}
)

# generate libfoo.jnilib
include_directories(${JNI_INCLUDE_DIRS} ${_classDir} ${_stubDir} ../../src/include)
include_directories(../../third_party/antlr4_cypher/include)
include_directories(../../third_party/antlr4_runtime/src)
include_directories(../../third_party/spdlog)
include_directories(../../third_party/nlohmann_json)
include_directories(../../third_party/pyparse)
include_directories(../../third_party/utf8proc/include)
include_directories(../../third_party/pybind11/include)
include_directories(../../third_party/re2/include)
include_directories(../../third_party/concurrentqueue)

find_library(KUZU NAMES kuzu PATHS ../../build/release/src)

add_library(kuzu_java_native MODULE kuzu_java.cpp KuzuNative.h)
set_target_properties(kuzu_java_native PROPERTIES SUFFIX ".dylib")
target_link_libraries(kuzu_java_native ${JNI_LIBRARIES} ${KUZU})

# add test to run JNIFoo
add_test(NAME Test
COMMAND ${Java_JAVA_EXECUTABLE}
-ea
-Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}
-cp ${_jarFile} tools.java_api.test)
104 changes: 104 additions & 0 deletions tools/java_api/KuzuConnection.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package tools.java_api;
import java.util.Map;

public class KuzuConnection {

long conn_ref;
boolean destroyed = false;

private void checkNotDestroyed () throws KuzuObjectRefDestroyedException {
if (destroyed)
throw new KuzuObjectRefDestroyedException("KuzuConnection has been destroyed.");
}

@Override
protected void finalize() throws KuzuObjectRefDestroyedException {
destroy();
}

public KuzuConnection(KuzuDatabase db) {
assert db != null: "Cannot create connection, database is null.";
conn_ref = KuzuNative.kuzu_connection_init(db);
}

public void destroy() throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_connection_destroy(this);
destroyed = true;
}

public void beginReadOnlyTransaction() throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_connection_begin_read_only_transaction(this);
}

public void beginWriteTransaction() throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_connection_begin_write_transaction(this);
}

public void commit() throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_connection_commit(this);
}

public void rollback() throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_connection_rollback(this);
}

public void setMaxNumThreadForExec(long num_threads) throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_connection_set_max_num_thread_for_exec(this, num_threads);
}

public long getMaxNumThreadForExec () throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_connection_get_max_num_thread_for_exec(this);
}

public KuzuQueryResult query (String queryStr) throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_connection_query(this, queryStr);
}

public KuzuPreparedStatement prepare (String queryStr) throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_connection_prepare(this, queryStr);
}

public KuzuQueryResult execute (KuzuPreparedStatement ps, Map<String, KuzuValue> m) throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_connection_execute(this, ps, m);
}

public String getNodeTableNames () throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_connection_get_node_table_names(this);
}

public String getRelTableNames () throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_connection_get_rel_table_names(this);
}

public String getNodePropertyNames (String table_name) throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_connection_get_node_property_names(this, table_name);
}

public String getRelPropertyNames (String table_name) throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_connection_get_rel_property_names(this, table_name);
}

public void interrupt () throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_connection_interrupt(this);
}

public void setQueryTimeout (long timeout_in_ms) throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_connection_set_query_timeout(this, timeout_in_ms);
}
}
59 changes: 59 additions & 0 deletions tools/java_api/KuzuDataType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package tools.java_api;

public class KuzuDataType {
long dt_ref;
boolean destroyed = false;

private void checkNotDestroyed () throws KuzuObjectRefDestroyedException {
if (destroyed)
throw new KuzuObjectRefDestroyedException("KuzuDatabase has been destroyed.");
}

@Override
protected void finalize() throws KuzuObjectRefDestroyedException {
destroy();
}

public void destroy() throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_data_type_destroy(this);
destroyed = true;
}

public KuzuDataType (KuzuDataTypeID id) {
dt_ref = KuzuNative.kuzu_data_type_create(id, null, 0);
}

public KuzuDataType
(KuzuDataTypeID id, KuzuDataType child_type, long fixed_num_elements_in_list) {
dt_ref = KuzuNative.kuzu_data_type_create(id, child_type, fixed_num_elements_in_list);
}

public KuzuDataType clone() {
if(destroyed)
return null;
else
return KuzuNative.kuzu_data_type_clone(this);
}

public boolean equals (KuzuDataType other) throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_data_type_equals(this, other);
}

public KuzuDataTypeID getID () throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_data_type_get_id(this);
}

public KuzuDataType getChildType () throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_data_type_get_child_type(this);
}

public long getFixedNumElementsInList () throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_data_type_get_fixed_num_elements_in_list(this);
}

}
27 changes: 27 additions & 0 deletions tools/java_api/KuzuDataTypeID.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package tools.java_api;

public enum KuzuDataTypeID {
ANY(0),
NODE(10),
REL(11),
BOOL(22),
INT64(23),
INT32(24),
INT16(25),
DOUBLE(26),
FLOAT(27),
DATE(28),
TIMESTAMP(29),
INTERVAL(30),
FIXED_LIST(31),
INTERNAL_ID(40),
STRING(50),
VAR_LIST(52),
STRUCT(53);

public final int value;

private KuzuDataTypeID(int v) {
this.value = v;
}
}
35 changes: 35 additions & 0 deletions tools/java_api/KuzuDatabase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package tools.java_api;

public class KuzuDatabase {

long db_ref;
String db_path;
long buffer_size;
boolean destroyed = false;

private void checkNotDestroyed () throws KuzuObjectRefDestroyedException {
if (destroyed)
throw new KuzuObjectRefDestroyedException("KuzuDatabase has been destroyed.");
}

@Override
protected void finalize() throws KuzuObjectRefDestroyedException {
destroy();
}

public KuzuDatabase (String database_path, long buffer_pool_size) {
this.db_path = database_path;
this.buffer_size = buffer_pool_size;
db_ref = KuzuNative.kuzu_database_init(database_path, buffer_pool_size);
}

public void destroy() throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_database_destroy(this);
destroyed = true;
}

public static void setLoggingLevel(String logging_level) {
KuzuNative.kuzu_database_set_logging_level(logging_level);
}
}
34 changes: 34 additions & 0 deletions tools/java_api/KuzuFlatTuple.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package tools.java_api;

public class KuzuFlatTuple {
long ft_ref;
boolean destroyed = false;

private void checkNotDestroyed () throws KuzuObjectRefDestroyedException {
if (destroyed)
throw new KuzuObjectRefDestroyedException("KuzuFlatTuple has been destroyed.");
}

@Override
protected void finalize() throws KuzuObjectRefDestroyedException {
destroy();
}

public void destroy () throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
KuzuNative.kuzu_flat_tuple_destroy(this);
destroyed = true;
}

public KuzuValue getValue (long index) throws KuzuObjectRefDestroyedException {
checkNotDestroyed();
return KuzuNative.kuzu_flat_tuple_get_value(this, index);
}

public String toString () {
if (destroyed)
return "KuzuFlatTuple has been destroyed.";
else
return KuzuNative.kuzu_flat_tuple_to_string(this);
}
}
11 changes: 11 additions & 0 deletions tools/java_api/KuzuInternalID.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package tools.java_api;

public class KuzuInternalID {
public long table_id;
public long offset;

public KuzuInternalID (long table_id, long offset) {
this.table_id = table_id;
this.offset = offset;
}
}
Loading

0 comments on commit d91ca92

Please sign in to comment.