v1.3.0

Tue, 12 Mar 2024 00:00:00 GMT

Features: * Introduced [`IF NOT EXISTS` clause on `DEFINE` statements](https://surrealdb.com/docs/surrealql/statements/define). * Implemented [`IF EXISTS` for additional `REMOVE` statements](https://surrealdb.com/docs/surrealql/statements/remove#using-if-exists-clause-since-130). * Changed the KNN operator from `<2>` to `<|2|>` in the new parser and added support in the old parser for the new syntax. * Implemented WebSocket session expiration. * Added support for tables and geometries in CBOR. * Added support for parsing decimal numbers with scientific notion. * Added support for printing a warning in the CLI when using an outdated version of SurrealDB. * Added `Surreal::wait_for` to make it possible for the client to wait for certain events. * Added SurrealKV as an unstable feature. * Added more error message improvements for the new parser. Bug fixes: * More consistent handling of negative numbers in record IDs. * Removed the unimplemented `backup` command from the CLI. * Fixed document not being available to delete permissions clause. * Ensured objects properties are recognized by the query planner. * Implemented the union strategy on unique indexes. Performance improvements: * Added compile-time feature for flamegraph and pprof profiling. #### `IF NOT EXISTS` clause on `DEFINE` statements `DEFINE` statements now allow you to include an `IF NOT EXISTS` clause which ensures that the define statement is only run if the resource doesn’t already exist. If it exists, you will get an error. Learn more about this in [the documentation](https://surrealdb.com/docs/surrealql/statements/define) ```surql DEFINE DATABASE IF NOT EXISTS example ``` #### New KNN syntax The KNN operator now supports a new syntax using `<|` and `|>` instead of `<` and `>`. Learn more about this in [the documentation](https://surrealdb.com/docs/surrealql/operators#knn-since-130) ```surql SELECT id FROM point WHERE point_b <|2|> [2, 3, 4, 5] ``` #### Waiting for client events It’s now possible to initialise the connection and run setup actions like authentication and selecting the database concurrently with other queries by making it possible to wait for the SDK to connect or select the database to use before allowing other queries to execute. Something like this would be susceptible to a race condition before: ```rust // A static, global instance of the client static DB: Lazy> = Lazy::new(|| { // Connect and setup the database connection in the background tokio::spawn(async { // This example is for demonstration purposes only. // If the `unwrap` panics the client will be left hanging, // waiting for the setup to happen when using `Surreal::wait_for`. setup_db().await.unwrap(); }); // Initialise a new unconnected instance of the client Surreal::init() }); // Connect to the server and run setup actions async fn setup_db() -> surrealdb::Result<()> { // Connect to the server DB.connect("ws://localhost:8000").await?; // Signin as a namespace, database, or root user DB.signin(Root { username: "root", password: "root", }).await?; // Select a specific namespace / database DB.use_ns("namespace").use_db("database").await?; Ok(()) } // Whether this would run successfully or return an error would depend on whether // `DB::setup` was able to execute before getting to this point. DB.create(Resource::from("person")).await?; ``` Now it’s possible to make the client wait for either the connection to be established ```rust use surrealdb::opt::WaitFor::Connection; // This will wait until the connection is established. // As soon as it is, it will return and allow the client to continue. DB.wait_for(Connection).await; // This will still likely return an error. // While we know that the connection is already established at this point, // there is no guarantee that the database has already been selected. // This query requires the database to be selected first. DB.create(Resource::from("person")).await?; ``` or the database to be selected. ```rust use surrealdb::opt::WaitFor::Database; // This will wait until the database is selected. // As soon as it is, it will return and allow the client to continue. DB.wait_for(Database).await; // At this point, the database is guaranteed to be selected already // so this query should run successfully. DB.create(Resource::from("person")).await?; ```