Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update api doc for java, nodejs, python and add pytest for in-mem mode #4095

Merged
merged 4 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/include/main/database.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ class Database {
public:
/**
* @brief Creates a database object.
* @param databasePath Database path.
* @param databasePath Database path. If the path is empty, or equal to `:memory:`, the database
* will be created in memory.
* @param systemConfig System configurations (buffer pool size and max num threads).
*/
KUZU_API explicit Database(std::string_view databasePath,
Expand Down
10 changes: 9 additions & 1 deletion tools/java_api/src/main/java/com/kuzudb/KuzuDatabase.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ public class KuzuDatabase {
boolean destroyed = false;
boolean readOnly = false;

/**
* Creates a database object. The database will be created in memory with default settings.
*/
public KuzuDatabase() {
this("");
}

/**
* Creates a database object.
* @param databasePath: Database path. If the database does not already exist, it will be created.
Expand All @@ -25,7 +32,8 @@ public KuzuDatabase(String databasePath) {

/**
* Creates a database object.
* @param databasePath: Database path. If the database does not already exist, it will be created.
* @param databasePath: Database path. If the path is empty, or equal to `:memory:`, the database will be created in
* memory.
* @param bufferPoolSize: Max size of the buffer pool in bytes.
* @param enableCompression: Enable compression in storage.
* @param readOnly: Open the database in READ_ONLY mode.
Expand Down
10 changes: 10 additions & 0 deletions tools/java_api/src/test/java/com/kuzudb/test/DatabaseTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,14 @@ void DBCreationAndDestroyWithPathOnly() {
fail("DBCreationAndDestroyWithPathOnly failed");
}
}

@Test
void DBCreationAndDestroyWithNoParam(){
try {
KuzuDatabase database = new KuzuDatabase();
database.destroy();
} catch (Exception e) {
fail("DBCreationAndDestroyWithNoParam failed");
}
}
}
10 changes: 7 additions & 3 deletions tools/nodejs_api/src_js/database.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ class Database {
* executed. To initialize the database immediately, call the `init()`
* function on the returned object.
*
* @param {String} databasePath path to the database file.
* @param {String} databasePath path to the database file. If the path is not specified, or empty, or equal to
`:memory:`, the database will be created in memory.
* @param {Number} bufferManagerSize size of the buffer manager in bytes.
* @param {Boolean} enableCompression whether to enable compression.
* @param {Boolean} readOnly if true, database will be opened in read-only mode.
Expand All @@ -19,13 +20,16 @@ class Database {
* address space limit some environment.
*/
constructor(
databasePath = "",
databasePath,
bufferManagerSize = 0,
enableCompression = true,
readOnly = false,
maxDBSize = 0
) {
if (typeof databasePath !== "string") {
if (!databasePath) {
databasePath = ":memory:";
}
else if (typeof databasePath !== "string") {
throw new Error("Database path must be a string.");
}
if (typeof bufferManagerSize !== "number" || bufferManagerSize < 0) {
Expand Down
42 changes: 42 additions & 0 deletions tools/nodejs_api/test/test_database.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,48 @@ describe("Database constructor", function () {
assert.equal(e.message, "Max DB size must be a positive integer.");
}
});

it("should create an in-memory database when no path is provided", async function () {
const testDb = new kuzu.Database();
const conn = new kuzu.Connection(testDb);
let res = await conn.query("CREATE NODE TABLE person(name STRING, age INT64, PRIMARY KEY(name));");
res.close();
res = await conn.query("CREATE (:person {name: 'Alice', age: 30});");
res.close();
res = await conn.query("CREATE (:person {name: 'Bob', age: 40});");
res.close();
res = await conn.query("MATCH (p:person) RETURN p.*;");
const result = await res.getAll();
assert.equal(result.length, 2);
assert.deepEqual(result, [
{ 'p.name': 'Alice', 'p.age': 30 },
{ 'p.name': 'Bob', 'p.age': 40 }
]);
res.close();
conn.close();
testDb.close();
});

it("should create an in-memory database when empty path is provided", async function () {
const testDb = new kuzu.Database("", 1 << 28 /* 256MB */);
const conn = new kuzu.Connection(testDb);
let res = await conn.query("CREATE NODE TABLE person(name STRING, age INT64, PRIMARY KEY(name));");
res.close();
res = await conn.query("CREATE (:person {name: 'Alice', age: 30});");
res.close();
res = await conn.query("CREATE (:person {name: 'Bob', age: 40});");
res.close();
res = await conn.query("MATCH (p:person) RETURN p.*;");
const result = await res.getAll();
assert.equal(result.length, 2);
assert.deepEqual(result, [
{ 'p.name': 'Alice', 'p.age': 30 },
{ 'p.name': 'Bob', 'p.age': 40 }
]);
res.close();
conn.close();
testDb.close();
});
});

describe("Database close", function () {
Expand Down
7 changes: 5 additions & 2 deletions tools/python_api/src_py/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Database:

def __init__(
self,
database_path: str | Path = "",
database_path: str | Path | None = None,
*,
buffer_pool_size: int = 0,
max_num_threads: int = 0,
Expand All @@ -40,7 +40,8 @@ def __init__(
Parameters
----------
database_path : str, Path
The path to database files
The path to database files. If the path is not specified, or empty, or equal to `:memory:`, the database
will be created in memory.

buffer_pool_size : int
The maximum size of buffer pool in bytes. Defaults to ~80% of system memory.
Expand Down Expand Up @@ -73,6 +74,8 @@ def __init__(
environment and 1GB under 32-bit one.

"""
if database_path is None:
database_path = ":memory:"
if isinstance(database_path, Path):
database_path = str(database_path)

Expand Down
42 changes: 42 additions & 0 deletions tools/python_api/test/test_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,45 @@ def test_database_context_manager(tmp_path: Path, build_dir: Path) -> None:
# TODO: Enable this test on Windows when the read-only mode is implemented.
if sys.platform != "win32":
open_database_on_subprocess(db_path, build_dir)


def test_in_mem_database_memory_db_path() -> None:
db = kuzu.Database(database_path=":memory:")
assert not db.is_closed
assert db._database is not None

# Open the database on a subprocess. It should raise an exception.
conn = kuzu.Connection(db)
conn.execute("CREATE NODE TABLE person(name STRING, age INT64, PRIMARY KEY(name));")
conn.execute("CREATE (:person {name: 'Alice', age: 30});")
conn.execute("CREATE (:person {name: 'Bob', age: 40});")
result = conn.execute("MATCH (p:person) RETURN p.*")
assert result.get_num_tuples() == 2


def test_in_mem_database_empty_db_path() -> None:
db = kuzu.Database()
assert not db.is_closed
assert db._database is not None

# Open the database on a subprocess. It should raise an exception.
conn = kuzu.Connection(db)
conn.execute("CREATE NODE TABLE person(name STRING, age INT64, PRIMARY KEY(name));")
conn.execute("CREATE (:person {name: 'Alice', age: 30});")
conn.execute("CREATE (:person {name: 'Bob', age: 40});")
result = conn.execute("MATCH (p:person) RETURN p.*")
assert result.get_num_tuples() == 2


def test_in_mem_database_no_db_path() -> None:
with kuzu.Database(database_path="") as db:
assert not db.is_closed
assert db._database is not None

# Open the database on a subprocess. It should raise an exception.
conn = kuzu.Connection(db)
conn.execute("CREATE NODE TABLE person(name STRING, age INT64, PRIMARY KEY(name));")
conn.execute("CREATE (:person {name: 'Alice', age: 30});")
conn.execute("CREATE (:person {name: 'Bob', age: 40});")
with conn.execute("MATCH (p:person) RETURN p.*") as result:
assert result.get_num_tuples() == 2