@@ -3,7 +3,7 @@ use super::datastore::locking_tx_datastore::datastore::TxMetrics;
33use super :: datastore:: locking_tx_datastore:: state_view:: {
44 IterByColEqMutTx , IterByColRangeMutTx , IterMutTx , IterTx , StateView ,
55} ;
6- use super :: datastore:: system_tables:: ST_MODULE_ID ;
6+ use super :: datastore:: system_tables:: { StFields , StVarFields , StVarName , StVarRow , ST_MODULE_ID , ST_VAR_ID } ;
77use super :: datastore:: traits:: {
88 InsertFlags , IsolationLevel , Metadata , MutTx as _, MutTxDatastore , Program , RowTypeForTable , Tx as _, TxDatastore ,
99 UpdateFlags ,
@@ -32,10 +32,12 @@ use spacetimedb_commitlog as commitlog;
3232use spacetimedb_durability:: { self as durability, TxOffset } ;
3333use spacetimedb_lib:: db:: auth:: StAccess ;
3434use spacetimedb_lib:: db:: raw_def:: v9:: { btree, RawModuleDefV9Builder , RawSql } ;
35+ use spacetimedb_lib:: st_var:: StVarValue ;
3536use spacetimedb_lib:: ConnectionId ;
3637use spacetimedb_lib:: Identity ;
3738use spacetimedb_paths:: server:: { CommitLogDir , ReplicaDir , SnapshotsPath } ;
3839use spacetimedb_primitives:: * ;
40+ use spacetimedb_sats:: algebraic_type:: fmt:: fmt_algebraic_type;
3941use spacetimedb_sats:: { AlgebraicType , AlgebraicValue , ProductType , ProductValue } ;
4042use spacetimedb_schema:: def:: { ModuleDef , TableDef } ;
4143use spacetimedb_schema:: schema:: { IndexSchema , RowLevelSecuritySchema , Schema , SequenceSchema , TableSchema } ;
@@ -44,6 +46,8 @@ use spacetimedb_table::indexes::RowPointer;
4446use spacetimedb_table:: page_pool:: PagePool ;
4547use spacetimedb_table:: table:: RowRef ;
4648use spacetimedb_table:: MemoryUsage ;
49+ use spacetimedb_vm:: errors:: { ErrorType , ErrorVm } ;
50+ use spacetimedb_vm:: ops:: parse;
4751use std:: borrow:: Cow ;
4852use std:: collections:: HashSet ;
4953use std:: fmt;
@@ -1388,6 +1392,78 @@ impl RelationalDB {
13881392 pub fn report ( & self , reducer : & str , metrics : & TxMetrics , tx_data : Option < & TxData > ) {
13891393 metrics. report ( tx_data, reducer, |wl : WorkloadType | self . exec_counters_for ( wl) ) ;
13901394 }
1395+
1396+ /// Read the value of [ST_VARNAME_ROW_LIMIT] from `st_var`
1397+ pub ( crate ) fn row_limit ( & self , tx : & Tx ) -> Result < Option < u64 > , DBError > {
1398+ let data = self . read_var ( tx, StVarName :: RowLimit ) ;
1399+
1400+ if let Some ( StVarValue :: U64 ( limit) ) = data? {
1401+ return Ok ( Some ( limit) ) ;
1402+ }
1403+ Ok ( None )
1404+ }
1405+
1406+ /// Read the value of [ST_VARNAME_SLOW_QRY] from `st_var`
1407+ pub ( crate ) fn query_limit ( & self , tx : & Tx ) -> Result < Option < u64 > , DBError > {
1408+ if let Some ( StVarValue :: U64 ( ms) ) = self . read_var ( tx, StVarName :: SlowQryThreshold ) ? {
1409+ return Ok ( Some ( ms) ) ;
1410+ }
1411+ Ok ( None )
1412+ }
1413+
1414+ /// Read the value of [ST_VARNAME_SLOW_SUB] from `st_var`
1415+ #[ allow( dead_code) ]
1416+ pub ( crate ) fn sub_limit ( & self , tx : & Tx ) -> Result < Option < u64 > , DBError > {
1417+ if let Some ( StVarValue :: U64 ( ms) ) = self . read_var ( tx, StVarName :: SlowSubThreshold ) ? {
1418+ return Ok ( Some ( ms) ) ;
1419+ }
1420+ Ok ( None )
1421+ }
1422+
1423+ /// Read the value of [ST_VARNAME_SLOW_INC] from `st_var`
1424+ #[ allow( dead_code) ]
1425+ pub ( crate ) fn incr_limit ( & self , tx : & Tx ) -> Result < Option < u64 > , DBError > {
1426+ if let Some ( StVarValue :: U64 ( ms) ) = self . read_var ( tx, StVarName :: SlowIncThreshold ) ? {
1427+ return Ok ( Some ( ms) ) ;
1428+ }
1429+ Ok ( None )
1430+ }
1431+
1432+ /// Read the value of a system variable from `st_var`
1433+ pub ( crate ) fn read_var ( & self , tx : & Tx , name : StVarName ) -> Result < Option < StVarValue > , DBError > {
1434+ if let Some ( row_ref) = self
1435+ . iter_by_col_eq ( tx, ST_VAR_ID , StVarFields :: Name . col_id ( ) , & name. into ( ) ) ?
1436+ . next ( )
1437+ {
1438+ return Ok ( Some ( StVarRow :: try_from ( row_ref) ?. value ) ) ;
1439+ }
1440+ Ok ( None )
1441+ }
1442+
1443+ /// Update the value of a system variable in `st_var`
1444+ pub ( crate ) fn write_var ( & self , tx : & mut MutTx , name : StVarName , literal : & str ) -> Result < ( ) , DBError > {
1445+ let value = Self :: parse_var ( name, literal) ?;
1446+ if let Some ( row_ref) = self
1447+ . iter_by_col_eq_mut ( tx, ST_VAR_ID , StVarFields :: Name . col_id ( ) , & name. into ( ) ) ?
1448+ . next ( )
1449+ {
1450+ self . delete ( tx, ST_VAR_ID , [ row_ref. pointer ( ) ] ) ;
1451+ }
1452+ tx. insert_via_serialize_bsatn ( ST_VAR_ID , & StVarRow { name, value } ) ?;
1453+ Ok ( ( ) )
1454+ }
1455+
1456+ /// Parse the literal representation of a system variable
1457+ fn parse_var ( name : StVarName , literal : & str ) -> Result < StVarValue , DBError > {
1458+ StVarValue :: try_from_primitive ( parse:: parse ( literal, & name. type_of ( ) ) ?) . map_err ( |v| {
1459+ ErrorVm :: Type ( ErrorType :: Parse {
1460+ value : literal. to_string ( ) ,
1461+ ty : fmt_algebraic_type ( & name. type_of ( ) ) . to_string ( ) ,
1462+ err : format ! ( "error parsing value: {:?}" , v) ,
1463+ } )
1464+ . into ( )
1465+ } )
1466+ }
13911467}
13921468
13931469#[ allow( unused) ]
@@ -1948,7 +2024,9 @@ mod tests {
19482024 system_tables, StConstraintRow , StIndexRow , StSequenceRow , StTableRow , ST_CONSTRAINT_ID , ST_INDEX_ID ,
19492025 ST_SEQUENCE_ID , ST_TABLE_ID ,
19502026 } ;
1951- use crate :: db:: relational_db:: tests_utils:: { begin_tx, insert, make_snapshot, TestDB } ;
2027+ use crate :: db:: relational_db:: tests_utils:: {
2028+ begin_tx, insert, make_snapshot, with_auto_commit, with_read_only, TestDB ,
2029+ } ;
19522030 use crate :: error:: IndexError ;
19532031 use crate :: execution_context:: ReducerContext ;
19542032 use anyhow:: bail;
@@ -2032,6 +2110,18 @@ mod tests {
20322110 Ok ( ( ) )
20332111 }
20342112
2113+ #[ test]
2114+ fn test_system_variables ( ) {
2115+ let db = TestDB :: durable ( ) . expect ( "failed to create db" ) ;
2116+ let _ = with_auto_commit ( & db, |tx| db. write_var ( tx, StVarName :: RowLimit , "5" ) ) ;
2117+ assert_eq ! (
2118+ 5 ,
2119+ with_read_only( & db, |tx| db. row_limit( tx) )
2120+ . expect( "failed to read from st_var" )
2121+ . expect( "row_limit does not exist" )
2122+ ) ;
2123+ }
2124+
20352125 #[ test]
20362126 fn test_open_twice ( ) -> ResultTest < ( ) > {
20372127 let stdb = TestDB :: durable ( ) ?;
0 commit comments