Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
cbff5f0
bump to latest beta
kearfy Feb 5, 2026
71e1bfd
3.0 features
kearfy Feb 5, 2026
1695f13
improve naming
kearfy Feb 5, 2026
6bd6673
fixes
kearfy Feb 5, 2026
8798e89
make valuemut and entrymut private
kearfy Feb 6, 2026
9e7bee1
Rename Thing to RecordId; fix isBigdecimal to isBigDecimal
kearfy Feb 9, 2026
989f410
Stage 1: RecordId with array and object keys
kearfy Feb 9, 2026
d012d32
Stage 2: version() and health()
kearfy Feb 9, 2026
28ff2b3
Stage 3: run()
kearfy Feb 9, 2026
f2b6303
Stage 4: export() and import()
kearfy Feb 9, 2026
3b50861
Stage 5: Live queries
kearfy Feb 9, 2026
9a5ae51
Stage 6: RecordIdRange type and select/update/delete/upsert overloads
kearfy Feb 9, 2026
ebe4da7
Stage 7: Value types FileRef, Range, Table, Regex
kearfy Feb 9, 2026
1798b1a
Drop Regex value type support; treat as serialization boundary
kearfy Feb 9, 2026
05eac68
Docs: align VALUE_TYPES_VALIDATION with implemented features
kearfy Feb 9, 2026
6de42a1
Add tests for plan changes; fix Surreal.run() varargs type
kearfy Feb 9, 2026
6c5edd2
add tests
kearfy Feb 9, 2026
8ec6fdb
fixes & fmt
kearfy Feb 9, 2026
365070c
fixup
kearfy Feb 9, 2026
dba11ee
try fix test
kearfy Feb 9, 2026
e00c87c
try fix ci
kearfy Feb 9, 2026
21f3b01
Revert "try fix ci"
kearfy Feb 9, 2026
a43bbf2
fixes
kearfy Feb 10, 2026
2345fcc
attempt fix
kearfy Feb 10, 2026
f132fcb
fix
kearfy Feb 10, 2026
9406dac
fix
kearfy Feb 10, 2026
370e065
fix
kearfy Feb 11, 2026
ca4eadd
try fix
kearfy Feb 11, 2026
6c73c21
fix
kearfy Feb 11, 2026
e0f4c0d
fix
kearfy Feb 11, 2026
9316fc0
fixup
kearfy Feb 11, 2026
7c6dec3
skipping test for now
kearfy Feb 11, 2026
c64203d
remove md file
kearfy Feb 11, 2026
2516d06
improve
kearfy Feb 11, 2026
0149cbc
Keep valuemut and entrymut public
kearfy Feb 11, 2026
7def82e
Add comments
kearfy Feb 11, 2026
e5d0d78
ensure transaction is marked as moved after commit or cancel
kearfy Feb 11, 2026
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
2,330 changes: 1,455 additions & 875 deletions Cargo.lock

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions src/main/java/com/surrealdb/NsDb.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.surrealdb;

/**
* Holds the current namespace and database after a {@link Surreal#useNs(String)},
* {@link Surreal#useDb(String)}, or {@link Surreal#useDefaults()} call.
* Returned by those methods so the client can use the actual ns/db set by the server.
*/
public class NsDb {

private final String namespace;
private final String database;

/**
* Creates an NsDb with the given namespace and database (both may be null).
*
* @param namespace the current namespace, or null
* @param database the current database, or null
*/
public NsDb(String namespace, String database) {
this.namespace = namespace;
this.database = database;
}

/**
* Returns the current namespace.
*
* @return the namespace, or null
*/
public String getNamespace() {
return namespace;
}

/**
* Returns the current database.
*
* @return the database, or null
*/
public String getDatabase() {
return database;
}
}
229 changes: 195 additions & 34 deletions src/main/java/com/surrealdb/Surreal.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
package com.surrealdb;

import com.surrealdb.signin.*;

import java.util.*;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.LongStream;
import java.util.stream.Stream;

import com.surrealdb.signin.Bearer;
import com.surrealdb.signin.Credential;
import com.surrealdb.signin.Database;
import com.surrealdb.signin.Namespace;
import com.surrealdb.signin.Record;
import com.surrealdb.signin.Root;
import com.surrealdb.signin.Signin;
import com.surrealdb.signin.Token;

/**
* The {@code Surreal} class provides methods to interact with a Surreal database.
* It includes functionality to connect to the database, sign in with different scopes,
Expand All @@ -18,26 +30,51 @@ public class Surreal extends Native implements AutoCloseable {
Loader.loadNative();
}

// Current namespace and database set by useNs() / useDb() / useDefaults() (from server return value).
private String namespace;
private String database;

/**
* Constructs a new Surreal object.
*/
public Surreal() {
super(Surreal.newInstance());
}

/**
* Constructor for a Surreal instance backed by an existing native pointer (e.g. from {@link #newSession()}).
*/
private Surreal(long ptr) {
super(ptr);
this.namespace = null;
this.database = null;
}

private static native long newInstance();

private static native long cloneSession(long ptr);

private static native boolean connect(long ptr, String connect);

private static native String signinRoot(long ptr, String username, String password);
private static native Token signinRoot(long ptr, String username, String password);

private static native Token signinNamespace(long ptr, String username, String password, String ns);

private static native String signinNamespace(long ptr, String username, String password, String ns);
private static native Token signinDatabase(long ptr, String username, String password, String ns, String db);

private static native String signinDatabase(long ptr, String username, String password, String ns, String db);
private static native Token signup(long ptr, String namespace, String database, String access, long paramsValuePtr);

private static native boolean useNs(long ptr, String ns);
private static native Token signinRecord(long ptr, String namespace, String database, String access, long paramsValuePtr);

private static native boolean useDb(long ptr, String ns);
private static native boolean authenticate(long ptr, String token);

private static native boolean invalidate(long ptr);

private static native NsDb useNs(long ptr, String ns);

private static native NsDb useDb(long ptr, String db);

private static native NsDb useDefaults(long ptr);

private static native long query(long ptr, String sql);

Expand Down Expand Up @@ -118,62 +155,186 @@ final boolean equals(long ptr1, long ptr2) {
*/
public Surreal connect(String connect) {
connect(getPtr(), connect);
namespace = null;
database = null;
return this;
}

/**
* Attempts to sign in to the Surreal system using the provided credentials.
* The type of signin object determines the scope of the sign-in (Root, Namespace, or Database).
* Signs in with the given credential. Supports Root, Namespace, Database, Record, and Bearer.
* <p>
* For more details, check the <a href="https://surrealdb.com/docs/surrealdb/security/authentication">authentication documentation</a>.
* <p>
*
* @param signin the credentials for signing in, which can be an instance of Root, Namespace, or Database
* @param credential the credentials (Root, Namespace, Database, Record, or Bearer)
* @return a Token representing the session after a successful sign-in
* @throws SurrealException if the credential type is unsupported or Record ns/db cannot be resolved
*/
public Token signin(Credential credential) {
if (credential instanceof Database) {
final Database db = (Database) credential;
return signinDatabase(getPtr(), db.getUsername(), db.getPassword(), db.getNamespace(), db.getDatabase());
} else if (credential instanceof Namespace) {
final Namespace ns = (Namespace) credential;
return signinNamespace(getPtr(), ns.getUsername(), ns.getPassword(), ns.getNamespace());
} else if (credential instanceof Root) {
final Root r = (Root) credential;
return signinRoot(getPtr(), r.getUsername(), r.getPassword());
} else if (credential instanceof Record) {
final Record rec = (Record) credential;
String ns = rec.getNamespace() != null ? rec.getNamespace() : this.namespace;
String db = rec.getDatabase() != null ? rec.getDatabase() : this.database;
if (ns == null || db == null) {
throw new SurrealException(
"Record signin requires namespace and database. Set them explicitly on Record or call useNs() and useDb() first.");
}
final ValueMut paramsValue = ValueBuilder.convert(rec.getParams());
return signinRecord(getPtr(), ns, db, rec.getAccess(), paramsValue.getPtr());
} else if (credential instanceof Bearer) {
Bearer bearer = (Bearer) credential;
authenticate(getPtr(), bearer.getToken());
return new Token(bearer.getToken(), null);
}
throw new SurrealException("Unsupported credential type: " + (credential != null ? credential.getClass().getName() : "null"));
}

/**
* Signs in with the given credentials (Root, Namespace, or Database).
*
* @param signin the credentials for signing in
* @return a Token representing the session token after a successful sign-in
* @throws SurrealException if the signin type is unsupported
* @deprecated Use {@link #signin(Credential)} with Root, Namespace, Database, Record, or Bearer.
*/
@Deprecated
public Token signin(Signin signin) {
if (signin instanceof Database) {
final Database db = (Database) signin;
return new Token(signinDatabase(getPtr(), db.getUsername(), db.getPassword(), db.getNamespace(), db.getDatabase()));
} else if (signin instanceof Namespace) {
final Namespace ns = (Namespace) signin;
return new Token(signinNamespace(getPtr(), ns.getUsername(), ns.getPassword(), ns.getNamespace()));
} else if (signin instanceof Root) {
final Root r = (Root) signin;
return new Token(signinRoot(getPtr(), r.getUsername(), r.getPassword()));
return signin((Credential) signin);
}

/**
* Signs up a record user with the given record access credentials.
* When namespace or database are null on the record, the current session values from useNs/useDb are used.
*
* @param record record signup credentials (namespace, database, access, params; ns/db may be null to use session)
* @return tokens (access and optional refresh) returned by the server
* @throws SurrealException if namespace or database cannot be resolved (call useNs/useDb first when omitting)
*/
public Token signup(Record record) {
String ns = record.getNamespace() != null ? record.getNamespace() : this.namespace;
String db = record.getDatabase() != null ? record.getDatabase() : this.database;
if (ns == null || db == null) {
throw new SurrealException(
"Record signup requires namespace and database. Set them explicitly on Record or call useNs() and useDb() first.");
}
throw new SurrealException("Unsupported sign in");
final ValueMut paramsValue = ValueBuilder.convert(record.getParams());
return signup(getPtr(), ns, db, record.getAccess(), paramsValue.getPtr());
}

/**
* Sets the namespace for the Surreal instance.
* <p>
* For more details, check the <a href="https://surrealdb.com/docs/surrealql/statements/use">use statement documentation</a>.
* <p>
* Authenticates the current connection with a JWT token (e.g. the access token from signin).
*
* @param token the access token string
* @return the current instance
*/
public Surreal authenticate(String token) {
authenticate(getPtr(), token);
return this;
}

/**
* Invalidates the authentication for the current connection.
*
* @return the current instance
*/
public Surreal invalidate() {
invalidate(getPtr());
return this;
}

/**
* Creates a new session that shares the same connection but has its own namespace, database,
* and authentication state. Use this for multi-session support.
*
* @return a new Surreal instance representing a separate session
*/
public Surreal newSession() {
return new Surreal(cloneSession(getPtr()));
}

private static native long beginTransaction(long ptr);

/**
* Starts a client-side transaction. Use {@link Transaction#query(String)} for operations
* and {@link Transaction#commit()} or {@link Transaction#cancel()} to complete it.
*
* @return a new Transaction instance
*/
public Transaction beginTransaction() {
return new Transaction(beginTransaction(getPtr()));
}

/**
* Sets the namespace for the Surreal instance. The current namespace and database from the server
* are stored; use {@link #getNamespace()} and {@link #getDatabase()} to read them.
*
* @param ns the namespace to use
* @return the current instance of the {@code Surreal} class
* @return this instance for chaining
*/
public Surreal useNs(String ns) {
useNs(getPtr(), ns);
NsDb result = useNs(getPtr(), ns);
this.namespace = result.getNamespace();
this.database = result.getDatabase();
return this;
}

/**
* Sets the database for the current instance of the Surreal class.
* <p>
* For more details, check the <a href="https://surrealdb.com/docs/surrealql/statements/use">use statement documentation</a>.
* <p>
* Sets the database for the current instance. The current namespace and database from the server
* are stored; use {@link #getNamespace()} and {@link #getDatabase()} to read them.
*
* @param db the database name to use
* @return the current instance of the {@code Surreal} class
* @return this instance for chaining
*/
public Surreal useDb(String db) {
useDb(getPtr(), db);
NsDb result = useDb(getPtr(), db);
this.namespace = result.getNamespace();
this.database = result.getDatabase();
return this;
}

/**
* Sets the default namespace and database. The actual defaults from the server are stored;
* use {@link #getNamespace()} and {@link #getDatabase()} to read them.
*
* @return this instance for chaining
*/
public Surreal useDefaults() {
NsDb result = useDefaults(getPtr());
this.namespace = result.getNamespace();
this.database = result.getDatabase();
return this;
}

/**
* Returns the current namespace set by the last {@link #useNs(String)}, {@link #useDb(String)},
* or {@link #useDefaults()} call (from the server response). Null if none of those have been
* called since {@link #connect(String)} or for a new session.
*
* @return the current namespace, or null
*/
public String getNamespace() {
return namespace;
}

/**
* Returns the current database set by the last {@link #useNs(String)}, {@link #useDb(String)},
* or {@link #useDefaults()} call (from the server response). Null if none of those have been
* called since {@link #connect(String)} or for a new session.
*
* @return the current database, or null
*/
public String getDatabase() {
return database;
}

/**
* Executes a SurrealQL query on the database.
* <p>
Expand Down
Loading
Loading