surrealdb-core 3.2.3

A scalable, distributed, collaborative, document-graph database, for the realtime web
Documentation
use anyhow::Result;
use surrealdb_types::ToSql;

use crate::err::Error;
use crate::val::{RecordId, RecordIdKey, TableName, Value};

impl Value {
	pub(crate) fn generate(self, tb: TableName, retable: bool) -> Result<RecordId> {
		match self {
			// There is a floating point number for the id field. Only accept
			// floats that round-trip exactly to an i64 (finite, whole, in
			// range). Lossy conversions are rejected — see
			// `Number::as_int_lossless`.
			Value::Number(id) if id.is_float() => {
				let key = id.as_int_lossless().map(RecordIdKey::Number).ok_or_else(|| {
					anyhow::Error::new(Error::IdInvalid {
						value: Value::Number(id).to_sql(),
					})
				})?;
				Ok(RecordId {
					table: tb,
					key,
				})
			}
			// There is an integer number for the id field
			Value::Number(id) if id.is_int() => Ok(RecordId {
				table: tb,
				key: RecordIdKey::Number(id.as_int()),
			}),
			// There is a string for the id field
			Value::String(id) if !id.is_empty() => Ok(RecordId {
				table: tb,
				key: id.into(),
			}),
			// There is an object for the id field
			Value::Object(id) => Ok(RecordId {
				table: tb,
				key: id.into(),
			}),
			// There is an array for the id field
			Value::Array(id) => Ok(RecordId {
				table: tb,
				key: id.into(),
			}),
			// There is a UUID for the id field
			Value::Uuid(id) => Ok(RecordId {
				table: tb,
				key: id.into(),
			}),
			// There is no record id field
			Value::None => Ok(RecordId {
				table: tb,
				key: RecordIdKey::rand(),
			}),
			// There is a record id defined
			Value::RecordId(id) => {
				if retable {
					// Let's re-table this record id
					Ok(RecordId {
						table: tb,
						key: id.key,
					})
				} else {
					// Let's use the specified record id
					if *tb == id.table {
						// The record is from the same table
						Ok(id)
					} else {
						// The record id is from another table
						Ok(RecordId {
							table: tb,
							key: id.key,
						})
					}
				}
			}
			// Any other value is wrong
			id => Err(anyhow::Error::new(Error::IdInvalid {
				value: id.to_sql(),
			})),
		}
	}
}