2022-07-28 09:00:06 +00:00
mod parse ;
use parse ::Parse ;
2023-08-30 18:01:30 +00:00
mod helpers ;
2024-09-10 10:10:46 +00:00
use crate ::helpers ::Test ;
2023-08-30 18:01:30 +00:00
use helpers ::new_ds ;
2022-12-30 08:23:19 +00:00
use surrealdb ::dbs ::Session ;
use surrealdb ::err ::Error ;
2023-07-29 18:47:25 +00:00
use surrealdb ::iam ::Role ;
2023-08-29 08:46:48 +00:00
use surrealdb ::sql ::Part ;
2022-07-28 09:00:06 +00:00
use surrealdb ::sql ::Value ;
#[ tokio::test ]
async fn insert_statement_object_single ( ) -> Result < ( ) , Error > {
let sql = "
2024-05-28 13:01:25 +00:00
INSERT INTO ` test - table ` {
2022-07-28 09:00:06 +00:00
id : ' tester ' ,
test : true ,
something : ' other ' ,
} ;
" ;
2023-08-30 18:01:30 +00:00
let dbs = new_ds ( ) . await ? ;
2023-07-29 18:47:25 +00:00
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
2023-07-05 21:26:13 +00:00
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
2022-07-28 09:00:06 +00:00
assert_eq! ( res . len ( ) , 1 ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
2024-05-28 13:01:25 +00:00
let val = Value ::parse ( " [{ id: `test-table`:tester, test: true, something: 'other' }] " ) ;
2022-07-28 09:00:06 +00:00
assert_eq! ( tmp , val ) ;
//
Ok ( ( ) )
}
#[ tokio::test ]
async fn insert_statement_object_multiple ( ) -> Result < ( ) , Error > {
let sql = "
INSERT INTO test [
{
id : 1 ,
test : true ,
something : ' other ' ,
} ,
{
id : 2 ,
test : false ,
something : ' else ' ,
} ,
] ;
" ;
2023-08-30 18:01:30 +00:00
let dbs = new_ds ( ) . await ? ;
2023-07-29 18:47:25 +00:00
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
2023-07-05 21:26:13 +00:00
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
2022-07-28 09:00:06 +00:00
assert_eq! ( res . len ( ) , 1 ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse (
" [
{ id : test :1 , test : true , something : ' other ' } ,
{ id : test :2 , test : false , something : ' else ' }
] " ,
) ;
assert_eq! ( tmp , val ) ;
//
Ok ( ( ) )
}
#[ tokio::test ]
async fn insert_statement_values_single ( ) -> Result < ( ) , Error > {
let sql = "
INSERT INTO test ( id , test , something ) VALUES ( ' tester ' , true , ' other ' ) ;
" ;
2023-08-30 18:01:30 +00:00
let dbs = new_ds ( ) . await ? ;
2023-07-29 18:47:25 +00:00
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
2023-07-05 21:26:13 +00:00
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
2022-07-28 09:00:06 +00:00
assert_eq! ( res . len ( ) , 1 ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse ( " [{ id: test:tester, test: true, something: 'other' }] " ) ;
assert_eq! ( tmp , val ) ;
//
Ok ( ( ) )
}
#[ tokio::test ]
async fn insert_statement_values_multiple ( ) -> Result < ( ) , Error > {
let sql = "
INSERT INTO test ( id , test , something ) VALUES ( 1 , true , ' other ' ) , ( 2 , false , ' else ' ) ;
" ;
2023-08-30 18:01:30 +00:00
let dbs = new_ds ( ) . await ? ;
2023-07-29 18:47:25 +00:00
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
2023-07-05 21:26:13 +00:00
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
2022-07-28 09:00:06 +00:00
assert_eq! ( res . len ( ) , 1 ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse (
" [
{ id : test :1 , test : true , something : ' other ' } ,
{ id : test :2 , test : false , something : ' else ' }
] " ,
) ;
assert_eq! ( tmp , val ) ;
//
Ok ( ( ) )
}
2022-09-30 20:33:33 +00:00
#[ tokio::test ]
async fn insert_statement_values_retable_id ( ) -> Result < ( ) , Error > {
let sql = "
INSERT INTO test ( id , test , something ) VALUES ( person :1 , true , ' other ' ) , ( person :2 , false , ' else ' ) ;
" ;
2023-08-30 18:01:30 +00:00
let dbs = new_ds ( ) . await ? ;
2023-07-29 18:47:25 +00:00
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
2023-07-05 21:26:13 +00:00
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
2022-09-30 20:33:33 +00:00
assert_eq! ( res . len ( ) , 1 ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse (
" [
{ id : test :1 , test : true , something : ' other ' } ,
{ id : test :2 , test : false , something : ' else ' }
] " ,
) ;
assert_eq! ( tmp , val ) ;
//
Ok ( ( ) )
}
2022-07-28 09:00:06 +00:00
#[ tokio::test ]
async fn insert_statement_on_duplicate_key ( ) -> Result < ( ) , Error > {
let sql = "
INSERT INTO test ( id , test , something ) VALUES ( ' tester ' , true , ' other ' ) ;
INSERT INTO test ( id , test , something ) VALUES ( ' tester ' , true , ' other ' ) ON DUPLICATE KEY UPDATE something = ' else ' ;
" ;
2023-08-30 18:01:30 +00:00
let dbs = new_ds ( ) . await ? ;
2023-07-29 18:47:25 +00:00
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
2023-07-05 21:26:13 +00:00
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
2022-07-28 09:00:06 +00:00
assert_eq! ( res . len ( ) , 2 ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse ( " [{ id: test:tester, test: true, something: 'other' }] " ) ;
assert_eq! ( tmp , val ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse ( " [{ id: test:tester, test: true, something: 'else' }] " ) ;
assert_eq! ( tmp , val ) ;
//
Ok ( ( ) )
}
2024-09-10 10:10:46 +00:00
#[ tokio::test ]
async fn insert_with_savepoint ( ) -> Result < ( ) , Error > {
let sql = "
2024-09-17 13:20:48 +00:00
DEFINE INDEX one ON pokemon FIELDS one UNIQUE ;
DEFINE INDEX two ON pokemon FIELDS two UNIQUE ;
- - This will INSERT a record with a specific id
INSERT INTO pokemon ( id , two ) VALUES ( 1 , ' two ' ) ;
- - This will INSERT a record with a random id
INSERT INTO pokemon ( id , one ) VALUES ( ' test ' , ' one ' ) ;
- - This will fail , because a UNIQUE index value already exists
INSERT INTO pokemon ( two ) VALUES ( ' two ' ) ;
- - This will fail , because a UNIQUE index value already exists
INSERT INTO pokemon ( id , one , two ) VALUES ( 2 , ' one ' , ' two ' ) ;
- - This will fail , because we are specifying a specific id even though we also have an ON DUPLICATE KEY UPDATE clause
INSERT INTO pokemon ( id , one , two ) VALUES ( 2 , ' one ' , ' two ' ) ON DUPLICATE KEY UPDATE two = ' changed ' ;
- - This will succeed , because we are not specifying a specific id and we also have an ON DUPLICATE KEY UPDATE clause
INSERT INTO pokemon ( one , two ) VALUES ( ' one ' , ' two ' ) ON DUPLICATE KEY UPDATE two = ' changed ' ;
2024-09-10 10:10:46 +00:00
SELECT * FROM pokemon ;
" ;
let mut t = Test ::new ( sql ) . await ? ;
t . expect_size ( 9 ) ? ;
t . skip_ok ( 2 ) ? ;
2024-09-17 13:20:48 +00:00
t . expect_val (
" [
{
id : pokemon :1 ,
two : ' two '
}
] " ,
) ? ;
t . expect_val (
" [
{
id : pokemon :test ,
one : ' one '
}
] " ,
) ? ;
t . expect_error ( " Database index `two` already contains 'two', with record `pokemon:1` " ) ? ;
t . expect_error ( " Database index `one` already contains 'one', with record `pokemon:test` " ) ? ;
t . expect_error ( " Database index `one` already contains 'one', with record `pokemon:test` " ) ? ;
t . expect_val (
" [
{
id : pokemon :test ,
one : ' one ' ,
two : ' changed '
}
] " ,
) ? ;
t . expect_val (
" [
{
id : pokemon :1 ,
two : ' two '
} ,
{
id : pokemon :test ,
one : ' one ' ,
two : ' changed '
}
] " ,
) ? ;
2024-09-10 10:10:46 +00:00
Ok ( ( ) )
}
2022-07-28 09:00:06 +00:00
#[ tokio::test ]
async fn insert_statement_output ( ) -> Result < ( ) , Error > {
let sql = "
INSERT INTO test ( id , test , something ) VALUES ( ' tester ' , true , ' other ' ) RETURN something ;
" ;
2023-08-30 18:01:30 +00:00
let dbs = new_ds ( ) . await ? ;
2023-07-29 18:47:25 +00:00
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
2023-07-05 21:26:13 +00:00
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
2022-07-28 09:00:06 +00:00
assert_eq! ( res . len ( ) , 1 ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse ( " [{ something: 'other' }] " ) ;
assert_eq! ( tmp , val ) ;
//
Ok ( ( ) )
}
2023-07-29 18:47:25 +00:00
2023-08-29 08:46:48 +00:00
#[ tokio::test ]
async fn insert_statement_duplicate_key_update ( ) -> Result < ( ) , Error > {
let sql = "
DEFINE INDEX name ON TABLE company COLUMNS name UNIQUE ;
INSERT INTO company ( name , founded ) VALUES ( ' SurrealDB ' , ' 2021 - 09 - 10 ' ) ON DUPLICATE KEY UPDATE founded = $input . founded ;
INSERT INTO company ( name , founded ) VALUES ( ' SurrealDB ' , ' 2021 - 09 - 11 ' ) ON DUPLICATE KEY UPDATE founded = $input . founded ;
INSERT INTO company ( name , founded ) VALUES ( ' SurrealDB ' , ' 2021 - 09 - 12 ' ) ON DUPLICATE KEY UPDATE founded = $input . founded PARALLEL ;
" ;
2023-08-30 18:01:30 +00:00
let dbs = new_ds ( ) . await ? ;
2023-08-29 08:46:48 +00:00
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
assert_eq! ( res . len ( ) , 4 ) ;
//
let tmp = res . remove ( 0 ) . result ;
assert! ( tmp . is_ok ( ) ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
assert_eq! ( tmp . first ( ) . pick ( & [ Part ::from ( " name " ) ] ) , Value ::from ( " SurrealDB " ) ) ;
assert_eq! ( tmp . first ( ) . pick ( & [ Part ::from ( " founded " ) ] ) , Value ::from ( " 2021-09-10 " ) ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
assert_eq! ( tmp . first ( ) . pick ( & [ Part ::from ( " name " ) ] ) , Value ::from ( " SurrealDB " ) ) ;
assert_eq! ( tmp . first ( ) . pick ( & [ Part ::from ( " founded " ) ] ) , Value ::from ( " 2021-09-11 " ) ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
assert_eq! ( tmp . first ( ) . pick ( & [ Part ::from ( " name " ) ] ) , Value ::from ( " SurrealDB " ) ) ;
assert_eq! ( tmp . first ( ) . pick ( & [ Part ::from ( " founded " ) ] ) , Value ::from ( " 2021-09-12 " ) ) ;
//
Ok ( ( ) )
}
2023-07-29 18:47:25 +00:00
//
// Permissions
//
async fn common_permissions_checks ( auth_enabled : bool ) {
let tests = vec! [
// Root level
( ( ( ) . into ( ) , Role ::Owner ) , ( " NS " , " DB " ) , true , " owner at root level should be able to insert a new record " ) ,
( ( ( ) . into ( ) , Role ::Editor ) , ( " NS " , " DB " ) , true , " editor at root level should be able to insert a new record " ) ,
( ( ( ) . into ( ) , Role ::Viewer ) , ( " NS " , " DB " ) , false , " viewer at root level should not be able to insert a new record " ) ,
// Namespace level
( ( ( " NS " , ) . into ( ) , Role ::Owner ) , ( " NS " , " DB " ) , true , " owner at namespace level should be able to insert a new record on its namespace " ) ,
( ( ( " NS " , ) . into ( ) , Role ::Owner ) , ( " OTHER_NS " , " DB " ) , false , " owner at namespace level should not be able to insert a new record on another namespace " ) ,
( ( ( " NS " , ) . into ( ) , Role ::Editor ) , ( " NS " , " DB " ) , true , " editor at namespace level should be able to insert a new record on its namespace " ) ,
( ( ( " NS " , ) . into ( ) , Role ::Editor ) , ( " OTHER_NS " , " DB " ) , false , " editor at namespace level should not be able to insert a new record on another namespace " ) ,
( ( ( " NS " , ) . into ( ) , Role ::Viewer ) , ( " NS " , " DB " ) , false , " viewer at namespace level should not be able to insert a new record on its namespace " ) ,
( ( ( " NS " , ) . into ( ) , Role ::Viewer ) , ( " OTHER_NS " , " DB " ) , false , " viewer at namespace level should not be able to insert a new record on another namespace " ) ,
// Database level
( ( ( " NS " , " DB " ) . into ( ) , Role ::Owner ) , ( " NS " , " DB " ) , true , " owner at database level should be able to insert a new record on its database " ) ,
( ( ( " NS " , " DB " ) . into ( ) , Role ::Owner ) , ( " NS " , " OTHER_DB " ) , false , " owner at database level should not be able to insert a new record on another database " ) ,
( ( ( " NS " , " DB " ) . into ( ) , Role ::Owner ) , ( " OTHER_NS " , " DB " ) , false , " owner at database level should not be able to insert a new record on another namespace even if the database name matches " ) ,
( ( ( " NS " , " DB " ) . into ( ) , Role ::Editor ) , ( " NS " , " DB " ) , true , " editor at database level should be able to insert a new record on its database " ) ,
( ( ( " NS " , " DB " ) . into ( ) , Role ::Editor ) , ( " NS " , " OTHER_DB " ) , false , " editor at database level should not be able to insert a new record on another database " ) ,
( ( ( " NS " , " DB " ) . into ( ) , Role ::Editor ) , ( " OTHER_NS " , " DB " ) , false , " editor at database level should not be able to insert a new record on another namespace even if the database name matches " ) ,
( ( ( " NS " , " DB " ) . into ( ) , Role ::Viewer ) , ( " NS " , " DB " ) , false , " viewer at database level should not be able to insert a new record on its database " ) ,
( ( ( " NS " , " DB " ) . into ( ) , Role ::Viewer ) , ( " NS " , " OTHER_DB " ) , false , " viewer at database level should not be able to insert a new record on another database " ) ,
( ( ( " NS " , " DB " ) . into ( ) , Role ::Viewer ) , ( " OTHER_NS " , " DB " ) , false , " viewer at database level should not be able to insert a new record on another namespace even if the database name matches " ) ,
] ;
let statement = " INSERT INTO person (id) VALUES ('id') " ;
for ( ( level , role ) , ( ns , db ) , should_succeed , msg ) in tests . into_iter ( ) {
let sess = Session ::for_level ( level , role ) . with_ns ( ns ) . with_db ( db ) ;
// Test the INSERT statement when the table has to be created
{
2023-08-30 18:01:30 +00:00
let ds = new_ds ( ) . await . unwrap ( ) . with_auth_enabled ( auth_enabled ) ;
2023-07-29 18:47:25 +00:00
let mut resp = ds . execute ( statement , & sess , None ) . await . unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
if should_succeed {
assert! ( res . is_ok ( ) & & res . unwrap ( ) ! = Value ::parse ( " [] " ) , " {} " , msg ) ;
} else if res . is_ok ( ) {
assert! ( res . unwrap ( ) = = Value ::parse ( " [] " ) , " {} " , msg ) ;
} else {
// Not allowed to create a table
let err = res . unwrap_err ( ) . to_string ( ) ;
assert! (
err . contains ( " Not enough permissions to perform this action " ) ,
" {}: {} " ,
msg ,
err
)
}
}
// Test the INSERT statement when the table already exists
{
2023-08-30 18:01:30 +00:00
let ds = new_ds ( ) . await . unwrap ( ) . with_auth_enabled ( auth_enabled ) ;
2023-07-29 18:47:25 +00:00
let mut resp = ds
. execute ( " CREATE person " , & Session ::owner ( ) . with_ns ( " NS " ) . with_db ( " DB " ) , None )
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! (
res . is_ok ( ) & & res . unwrap ( ) ! = Value ::parse ( " [] " ) ,
" unexpected error creating person record "
) ;
let mut resp = ds
. execute ( " CREATE person " , & Session ::owner ( ) . with_ns ( " OTHER_NS " ) . with_db ( " DB " ) , None )
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! (
res . is_ok ( ) & & res . unwrap ( ) ! = Value ::parse ( " [] " ) ,
" unexpected error creating person record "
) ;
let mut resp = ds
. execute ( " CREATE person " , & Session ::owner ( ) . with_ns ( " NS " ) . with_db ( " OTHER_DB " ) , None )
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! (
res . is_ok ( ) & & res . unwrap ( ) ! = Value ::parse ( " [] " ) ,
" unexpected error creating person record "
) ;
// Run the test
let mut resp = ds . execute ( statement , & sess , None ) . await . unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
if should_succeed {
assert! ( res . is_ok ( ) & & res . unwrap ( ) ! = Value ::parse ( " [] " ) , " {} " , msg ) ;
} else if res . is_ok ( ) {
assert! ( res . unwrap ( ) = = Value ::parse ( " [] " ) , " {} " , msg ) ;
} else {
// Not allowed to create a table
let err = res . unwrap_err ( ) . to_string ( ) ;
assert! (
err . contains ( " Not enough permissions to perform this action " ) ,
" {}: {} " ,
msg ,
err
)
}
}
}
}
#[ tokio::test ]
async fn check_permissions_auth_enabled ( ) {
let auth_enabled = true ;
//
// Test common scenarios
//
common_permissions_checks ( auth_enabled ) . await ;
//
// Test Anonymous user
//
// When the table doesn't exist
{
2023-08-30 18:01:30 +00:00
let ds = new_ds ( ) . await . unwrap ( ) . with_auth_enabled ( auth_enabled ) ;
2023-07-29 18:47:25 +00:00
let mut resp = ds
. execute (
" INSERT INTO person (id) VALUES ('id') " ,
& Session ::default ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
let err = res . unwrap_err ( ) . to_string ( ) ;
assert! (
err . contains ( " Not enough permissions to perform this action " ) ,
" anonymous user should not be able to create the table: {} " ,
err
) ;
}
// When the table exists but grants no permissions
{
2023-08-30 18:01:30 +00:00
let ds = new_ds ( ) . await . unwrap ( ) . with_auth_enabled ( auth_enabled ) ;
2023-07-29 18:47:25 +00:00
let mut resp = ds
. execute (
" DEFINE TABLE person PERMISSIONS NONE " ,
& Session ::owner ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! ( res . is_ok ( ) , " failed to create table: {:?} " , res ) ;
let mut resp = ds
. execute (
" INSERT INTO person (id) VALUES ('id') " ,
& Session ::default ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! ( res . unwrap ( ) = = Value ::parse ( " [] " ) , " {} " , " anonymous user should not be able to insert a new record if the table exists but has no permissions " ) ;
}
// When the table exists and grants full permissions
{
2023-08-30 18:01:30 +00:00
let ds = new_ds ( ) . await . unwrap ( ) . with_auth_enabled ( auth_enabled ) ;
2023-07-29 18:47:25 +00:00
let mut resp = ds
. execute (
" DEFINE TABLE person PERMISSIONS FULL " ,
& Session ::owner ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! ( res . is_ok ( ) , " failed to create table: {:?} " , res ) ;
let mut resp = ds
. execute (
" INSERT INTO person (id) VALUES ('id') " ,
& Session ::default ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! ( res . unwrap ( ) ! = Value ::parse ( " [] " ) , " {} " , " anonymous user should be able to insert a new record if the table exists and grants full permissions " ) ;
}
}
#[ tokio::test ]
async fn check_permissions_auth_disabled ( ) {
let auth_enabled = false ;
//
// Test common scenarios
//
common_permissions_checks ( auth_enabled ) . await ;
//
// Test Anonymous user
//
// When the table doesn't exist
{
2023-08-30 18:01:30 +00:00
let ds = new_ds ( ) . await . unwrap ( ) . with_auth_enabled ( auth_enabled ) ;
2023-07-29 18:47:25 +00:00
let mut resp = ds
. execute (
" INSERT INTO person (id) VALUES ('id') " ,
& Session ::default ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! (
res . unwrap ( ) ! = Value ::parse ( " [] " ) ,
" {} " ,
" anonymous user should be able to create the table "
) ;
}
// When the table exists but grants no permissions
{
2023-08-30 18:01:30 +00:00
let ds = new_ds ( ) . await . unwrap ( ) . with_auth_enabled ( auth_enabled ) ;
2023-07-29 18:47:25 +00:00
let mut resp = ds
. execute (
" DEFINE TABLE person PERMISSIONS NONE " ,
& Session ::owner ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! ( res . is_ok ( ) , " failed to create table: {:?} " , res ) ;
let mut resp = ds
. execute (
" INSERT INTO person (id) VALUES ('id') " ,
& Session ::default ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! ( res . unwrap ( ) ! = Value ::parse ( " [] " ) , " {} " , " anonymous user should not be able to insert a new record if the table exists but has no permissions " ) ;
}
// When the table exists and grants full permissions
{
2023-08-30 18:01:30 +00:00
let ds = new_ds ( ) . await . unwrap ( ) . with_auth_enabled ( auth_enabled ) ;
2023-07-29 18:47:25 +00:00
let mut resp = ds
. execute (
" DEFINE TABLE person PERMISSIONS FULL " ,
& Session ::owner ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! ( res . is_ok ( ) , " failed to create table: {:?} " , res ) ;
let mut resp = ds
. execute (
" INSERT INTO person (id) VALUES ('id') " ,
& Session ::default ( ) . with_ns ( " NS " ) . with_db ( " DB " ) ,
None ,
)
. await
. unwrap ( ) ;
let res = resp . remove ( 0 ) . output ( ) ;
assert! ( res . unwrap ( ) ! = Value ::parse ( " [] " ) , " {} " , " anonymous user should be able to insert a new record if the table exists and grants full permissions " ) ;
}
}
2023-12-07 14:45:12 +00:00
#[ tokio::test ]
async fn insert_statement_unique_index ( ) -> Result < ( ) , Error > {
let sql = "
DEFINE INDEX name ON TABLE company COLUMNS name UNIQUE ;
INSERT INTO company { name : ' SurrealDB ' } ;
INSERT INTO company { name : ' SurrealDB ' } ;
SELECT count ( ) FROM company GROUP ALL ;
" ;
let dbs = new_ds ( ) . await ? ;
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
assert_eq! ( res . len ( ) , 4 ) ;
//
let tmp = res . remove ( 0 ) . result ;
assert! ( tmp . is_ok ( ) ) ;
//
let tmp = res . remove ( 0 ) . result ;
assert! ( tmp . is_ok ( ) ) ;
//
let tmp = res . remove ( 0 ) . result ;
2024-09-17 13:20:48 +00:00
match tmp {
Err ( Error ::IndexExists {
index ,
value ,
..
} ) if index . eq ( " name " ) & & value . eq ( " 'SurrealDB' " ) = > ( ) ,
found = > panic! ( " Expected Err(Error::IndexExists), found ' {:?} ' " , found ) ,
}
2023-12-07 14:45:12 +00:00
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse ( " [ { count: 1 } ] " ) ;
assert_eq! ( tmp , val ) ;
//
Ok ( ( ) )
}
2024-05-28 12:37:16 +00:00
#[ tokio::test ]
async fn insert_relation ( ) -> Result < ( ) , Error > {
let sql = "
INSERT INTO person [
{ id : person :1 } ,
{ id : person :2 } ,
{ id : person :3 } ,
] ;
INSERT RELATION INTO likes {
in : person :1 ,
id : ' object ' ,
out : person :2 ,
} ;
INSERT RELATION INTO likes [
{
in : person :1 ,
id : ' array ' ,
out : person :2 ,
} ,
{
in : person :2 ,
id : ' array_twoo ' ,
out : person :3 ,
}
] ;
INSERT RELATION INTO likes ( in , id , out )
VALUES ( person :1 , ' values ' , person :2 ) ;
SELECT VALUE ->likes FROM person ;
" ;
let dbs = new_ds ( ) . await ? ;
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
assert_eq! ( res . len ( ) , 5 ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse ( " [{ id: person:1 }, { id: person:2 }, { id: person:3 }] " ) ;
assert_eq! ( tmp , val ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse (
"
[
{
id : likes :object ,
in : person :1 ,
out : person :2
}
]
" ,
) ;
assert_eq! ( tmp , val ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse (
"
[
{
id : likes :array ,
in : person :1 ,
out : person :2
} ,
{
id : likes :array_twoo ,
in : person :2 ,
out : person :3
}
]
" ,
) ;
assert_eq! ( tmp , val ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse (
"
[
{
id : likes :values ,
in : person :1 ,
out : person :2
}
]
" ,
) ;
assert_eq! ( tmp , val ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse (
"
[
[
likes :array ,
likes :object ,
likes :values
] ,
[
likes :array_twoo
] ,
[ ]
]
" ,
) ;
assert_eq! ( tmp , val ) ;
//
Ok ( ( ) )
}
#[ tokio::test ]
async fn insert_invalid_relation ( ) -> Result < ( ) , Error > {
let sql = "
INSERT RELATION INTO likes {
id : ' object ' ,
} ;
INSERT RELATION {
in : person :1 ,
} ;
" ;
let dbs = new_ds ( ) . await ? ;
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
assert_eq! ( res . len ( ) , 2 ) ;
//
match res . remove ( 0 ) . result {
Err ( Error ::InsertStatementIn {
value ,
} ) if value = = " NONE " = > ( ) ,
found = > panic! ( " Expected Err(Error::InsertStatementIn), found ' {:?} ' " , found ) ,
}
//
match res . remove ( 0 ) . result {
Err ( Error ::InsertStatementId {
value ,
} ) if value = = " NONE " = > ( ) ,
found = > panic! ( " Expected Err(Error::InsertStatementId), found ' {:?} ' " , found ) ,
}
//
Ok ( ( ) )
}
#[ tokio::test ]
async fn insert_without_into ( ) -> Result < ( ) , Error > {
let sql = "
INSERT [
{ id : test :1 }
] ;
INSERT { id : test :2 } ;
INSERT ( id ) VALUES ( test :3 ) ;
INSERT { } ;
" ;
let dbs = new_ds ( ) . await ? ;
let ses = Session ::owner ( ) . with_ns ( " test " ) . with_db ( " test " ) ;
let res = & mut dbs . execute ( sql , & ses , None ) . await ? ;
assert_eq! ( res . len ( ) , 4 ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse ( " [{ id: test:1 }] " ) ;
assert_eq! ( tmp , val ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse ( " [{ id: test:2 }] " ) ;
assert_eq! ( tmp , val ) ;
//
let tmp = res . remove ( 0 ) . result ? ;
let val = Value ::parse ( " [{ id: test:3 }] " ) ;
assert_eq! ( tmp , val ) ;
//
match res . remove ( 0 ) . result {
Err ( Error ::InsertStatementId {
value ,
} ) if value = = " NONE " = > ( ) ,
found = > panic! ( " Expected Err(Error::RelateStatementId), found ' {:?} ' " , found ) ,
}
//
Ok ( ( ) )
}