@@ -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 ,
@@ -31,10 +31,12 @@ use spacetimedb_commitlog as commitlog;
3131use spacetimedb_durability:: { self as durability, TxOffset } ;
3232use spacetimedb_lib:: db:: auth:: StAccess ;
3333use spacetimedb_lib:: db:: raw_def:: v9:: { btree, RawModuleDefV9Builder , RawSql } ;
34+ use spacetimedb_lib:: st_var:: StVarValue ;
3435use spacetimedb_lib:: ConnectionId ;
3536use spacetimedb_lib:: Identity ;
3637use spacetimedb_paths:: server:: { CommitLogDir , ReplicaDir , SnapshotsPath } ;
3738use spacetimedb_primitives:: * ;
39+ use spacetimedb_sats:: algebraic_type:: fmt:: fmt_algebraic_type;
3840use spacetimedb_sats:: { AlgebraicType , AlgebraicValue , ProductType , ProductValue } ;
3941use spacetimedb_schema:: def:: { ModuleDef , TableDef } ;
4042use spacetimedb_schema:: schema:: { IndexSchema , RowLevelSecuritySchema , Schema , SequenceSchema , TableSchema } ;
@@ -43,6 +45,8 @@ use spacetimedb_table::indexes::RowPointer;
4345use spacetimedb_table:: page_pool:: PagePool ;
4446use spacetimedb_table:: table:: RowRef ;
4547use spacetimedb_table:: MemoryUsage ;
48+ use spacetimedb_vm:: errors:: { ErrorType , ErrorVm } ;
49+ use spacetimedb_vm:: ops:: parse;
4650use std:: borrow:: Cow ;
4751use std:: collections:: HashSet ;
4852use std:: fmt;
@@ -1381,6 +1385,78 @@ impl RelationalDB {
13811385 pub fn report ( & self , reducer : & str , metrics : & TxMetrics , tx_data : Option < & TxData > ) {
13821386 metrics. report ( tx_data, reducer, |wl : WorkloadType | self . exec_counters_for ( wl) ) ;
13831387 }
1388+
1389+ /// Read the value of [ST_VARNAME_ROW_LIMIT] from `st_var`
1390+ pub ( crate ) fn row_limit ( & self , tx : & Tx ) -> Result < Option < u64 > , DBError > {
1391+ let data = self . read_var ( tx, StVarName :: RowLimit ) ;
1392+
1393+ if let Some ( StVarValue :: U64 ( limit) ) = data? {
1394+ return Ok ( Some ( limit) ) ;
1395+ }
1396+ Ok ( None )
1397+ }
1398+
1399+ /// Read the value of [ST_VARNAME_SLOW_QRY] from `st_var`
1400+ pub ( crate ) fn query_limit ( & self , tx : & Tx ) -> Result < Option < u64 > , DBError > {
1401+ if let Some ( StVarValue :: U64 ( ms) ) = self . read_var ( tx, StVarName :: SlowQryThreshold ) ? {
1402+ return Ok ( Some ( ms) ) ;
1403+ }
1404+ Ok ( None )
1405+ }
1406+
1407+ /// Read the value of [ST_VARNAME_SLOW_SUB] from `st_var`
1408+ #[ allow( dead_code) ]
1409+ pub ( crate ) fn sub_limit ( & self , tx : & Tx ) -> Result < Option < u64 > , DBError > {
1410+ if let Some ( StVarValue :: U64 ( ms) ) = self . read_var ( tx, StVarName :: SlowSubThreshold ) ? {
1411+ return Ok ( Some ( ms) ) ;
1412+ }
1413+ Ok ( None )
1414+ }
1415+
1416+ /// Read the value of [ST_VARNAME_SLOW_INC] from `st_var`
1417+ #[ allow( dead_code) ]
1418+ pub ( crate ) fn incr_limit ( & self , tx : & Tx ) -> Result < Option < u64 > , DBError > {
1419+ if let Some ( StVarValue :: U64 ( ms) ) = self . read_var ( tx, StVarName :: SlowIncThreshold ) ? {
1420+ return Ok ( Some ( ms) ) ;
1421+ }
1422+ Ok ( None )
1423+ }
1424+
1425+ /// Read the value of a system variable from `st_var`
1426+ pub ( crate ) fn read_var ( & self , tx : & Tx , name : StVarName ) -> Result < Option < StVarValue > , DBError > {
1427+ if let Some ( row_ref) = self
1428+ . iter_by_col_eq ( tx, ST_VAR_ID , StVarFields :: Name . col_id ( ) , & name. into ( ) ) ?
1429+ . next ( )
1430+ {
1431+ return Ok ( Some ( StVarRow :: try_from ( row_ref) ?. value ) ) ;
1432+ }
1433+ Ok ( None )
1434+ }
1435+
1436+ /// Update the value of a system variable in `st_var`
1437+ pub ( crate ) fn write_var ( & self , tx : & mut MutTx , name : StVarName , literal : & str ) -> Result < ( ) , DBError > {
1438+ let value = Self :: parse_var ( name, literal) ?;
1439+ if let Some ( row_ref) = self
1440+ . iter_by_col_eq_mut ( tx, ST_VAR_ID , StVarFields :: Name . col_id ( ) , & name. into ( ) ) ?
1441+ . next ( )
1442+ {
1443+ self . delete ( tx, ST_VAR_ID , [ row_ref. pointer ( ) ] ) ;
1444+ }
1445+ tx. insert_via_serialize_bsatn ( ST_VAR_ID , & StVarRow { name, value } ) ?;
1446+ Ok ( ( ) )
1447+ }
1448+
1449+ /// Parse the literal representation of a system variable
1450+ fn parse_var ( name : StVarName , literal : & str ) -> Result < StVarValue , DBError > {
1451+ StVarValue :: try_from_primitive ( parse:: parse ( literal, & name. type_of ( ) ) ?) . map_err ( |v| {
1452+ ErrorVm :: Type ( ErrorType :: Parse {
1453+ value : literal. to_string ( ) ,
1454+ ty : fmt_algebraic_type ( & name. type_of ( ) ) . to_string ( ) ,
1455+ err : format ! ( "error parsing value: {:?}" , v) ,
1456+ } )
1457+ . into ( )
1458+ } )
1459+ }
13841460}
13851461
13861462#[ allow( unused) ]
@@ -1941,7 +2017,9 @@ mod tests {
19412017 system_tables, StConstraintRow , StIndexRow , StSequenceRow , StTableRow , ST_CONSTRAINT_ID , ST_INDEX_ID ,
19422018 ST_SEQUENCE_ID , ST_TABLE_ID ,
19432019 } ;
1944- use crate :: db:: relational_db:: tests_utils:: { begin_tx, insert, make_snapshot, TestDB } ;
2020+ use crate :: db:: relational_db:: tests_utils:: {
2021+ begin_tx, insert, make_snapshot, with_auto_commit, with_read_only, TestDB ,
2022+ } ;
19452023 use crate :: error:: IndexError ;
19462024 use crate :: execution_context:: ReducerContext ;
19472025 use anyhow:: bail;
@@ -2025,6 +2103,18 @@ mod tests {
20252103 Ok ( ( ) )
20262104 }
20272105
2106+ #[ test]
2107+ fn test_system_variables ( ) {
2108+ let db = TestDB :: durable ( ) . expect ( "failed to create db" ) ;
2109+ let _ = with_auto_commit ( & db, |tx| db. write_var ( tx, StVarName :: RowLimit , "5" ) ) ;
2110+ assert_eq ! (
2111+ 5 ,
2112+ with_read_only( & db, |tx| db. row_limit( tx) )
2113+ . expect( "failed to read from st_var" )
2114+ . expect( "row_limit does not exist" )
2115+ ) ;
2116+ }
2117+
20282118 #[ test]
20292119 fn test_open_twice ( ) -> ResultTest < ( ) > {
20302120 let stdb = TestDB :: durable ( ) ?;
0 commit comments