@@ -118,9 +118,7 @@ fn _detect_version(spot: &OpenedSpot) -> Result<DetectedVersion> {
118118fn _get_instances ( spot : & OpenedSpot , custom_query : Option < & str > ) -> Result < _InstanceEntries > {
119119 if let Some ( query) = custom_query {
120120 // Replaces the probe entirely; the caller owns the column set.
121- return Ok ( _to_instance_entries (
122- spot. query_table ( & SqlQuery :: new ( query, & Vec :: new ( ) ) ) . 0 ?,
123- ) ) ;
121+ return _to_instance_entries ( spot. query_table ( & SqlQuery :: new ( query, & Vec :: new ( ) ) ) . 0 ?) ;
124122 }
125123
126124 let detected = _detect_version ( spot) ?;
@@ -143,7 +141,7 @@ fn _get_instances(spot: &OpenedSpot, custom_query: Option<&str>) -> Result<_Inst
143141 * version_column = detected. version ( ) . clone ( ) . into ( ) ;
144142 }
145143 }
146- Ok ( _to_instance_entries ( result) )
144+ _to_instance_entries ( result)
147145}
148146
149147fn _extract_version ( result : Vec < String > ) -> Option < String > {
@@ -158,25 +156,29 @@ fn _extract_version(result: Vec<String>) -> Option<String> {
158156 . map ( str:: to_string)
159157}
160158
161- fn _to_instance_entries ( result : Vec < Vec < String > > ) -> _InstanceEntries {
162- let hashmap: _InstanceEntries = result
159+ /// Consumes columns 0, 2 and 4. Instance info we cannot interpret fails the
160+ /// endpoint, which surfaces as a FAILURE row, rather than guessing a tenancy
161+ /// that would silently reshape every section.
162+ fn _to_instance_entries ( result : Vec < Vec < String > > ) -> Result < _InstanceEntries > {
163+ result
163164 . into_iter ( )
164- . filter_map ( |x| {
165- if x. len ( ) < 2 {
166- log:: error!(
167- "Unexpected result from v$instance: expected at least 2 columns, got {}" ,
168- x. len( )
165+ . map ( |row| {
166+ let ( Some ( name) , Some ( version) , Some ( tenant) ) = ( row. first ( ) , row. get ( 2 ) , row. get ( 4 ) )
167+ else {
168+ anyhow:: bail!(
169+ "Unexpected result from v$instance: expected at least 5 columns, got {}" ,
170+ row. len( )
169171 ) ;
170- None
171- } else {
172- Some ( (
173- InstanceName :: from ( x[ 0 ] . as_str ( ) ) ,
174- ( InstanceVersion :: from ( x[ 2 ] . clone ( ) ) , Tenant :: new ( & x[ 4 ] ) ) ,
175- ) )
176- }
172+ } ;
173+ let tenant = Tenant :: from_cdb_column ( tenant) . ok_or_else ( || {
174+ anyhow:: anyhow!( "Unexpected v$database.cdb value '{tenant}' for instance {name}" )
175+ } ) ?;
176+ Ok ( (
177+ InstanceName :: from ( name. as_str ( ) ) ,
178+ ( InstanceVersion :: from ( version. clone ( ) ) , tenant) ,
179+ ) )
177180 } )
178- . collect ( ) ;
179- hashmap
181+ . collect ( )
180182}
181183pub fn convert_to_num_version ( version : & InstanceVersion ) -> Option < InstanceNumVersion > {
182184 let tops = String :: from ( version. clone ( ) )
@@ -198,7 +200,7 @@ pub fn convert_to_num_version(version: &InstanceVersion) -> Option<InstanceNumVe
198200mod tests {
199201 use super :: * ;
200202 use crate :: config:: ora_sql:: Endpoint ;
201- use crate :: ora_sql:: backend:: test_support:: MiniOra ;
203+ use crate :: ora_sql:: backend:: test_support:: { instance_row , MiniOra } ;
202204 use crate :: ora_sql:: backend:: SpotBuilder ;
203205
204206 /// Returns the derived (version, tenant) plus every query the run issued.
@@ -322,6 +324,30 @@ mod tests {
322324 . is_none( ) ) ;
323325 }
324326
327+ #[ test]
328+ fn test_instance_entries_tenant_from_cdb_column ( ) {
329+ for ( cdb, expected) in [ ( "NO" , Tenant :: NoCdb ) , ( "YES" , Tenant :: Cdb ) ] {
330+ let entries =
331+ _to_instance_entries ( vec ! [ instance_row( "ORCL" , "19.28.0.0.0" , cdb) ] ) . unwrap ( ) ;
332+ assert_eq ! (
333+ entries. get( & InstanceName :: from( "ORCL" ) ) . unwrap( ) . 1 ,
334+ expected
335+ ) ;
336+ }
337+ }
338+
339+ #[ test]
340+ fn test_instance_entries_short_row_is_skipped_not_panic ( ) {
341+ for row in [ vec ! [ "ORCL" . to_string( ) ] , vec ! [ "ORCL" . into( ) , "0" . into( ) ] ] {
342+ assert ! ( _to_instance_entries( vec![ row] ) . is_err( ) ) ;
343+ }
344+ }
345+
346+ #[ test]
347+ fn test_instance_entries_unknown_cdb_value_fails ( ) {
348+ assert ! ( _to_instance_entries( vec![ instance_row( "ORCL" , "19.28.0.0.0" , "MAYBE" ) ] ) . is_err( ) ) ;
349+ }
350+
325351 #[ test]
326352 fn test_convert_to_num_version ( ) {
327353 assert_eq ! (
0 commit comments