@@ -10,7 +10,11 @@ use common::{
1010 database_index:: IndexedFields ,
1111 INDEX_TABLE ,
1212 } ,
13- document:: GenericDocument ,
13+ document:: {
14+ DeveloperDocument ,
15+ GenericDocument ,
16+ ResolvedDocument ,
17+ } ,
1418 index:: IndexKeyBytes ,
1519 interval:: Interval ,
1620 query:: {
@@ -24,6 +28,7 @@ use common::{
2428 runtime:: Runtime ,
2529 types:: {
2630 IndexName ,
31+ TabletIndexName ,
2732 WriteTimestamp ,
2833 } ,
2934 version:: Version ,
@@ -110,6 +115,10 @@ trait QueryStream<T: QueryType>: Send {
110115 prefetch_hint : Option < usize > ,
111116 ) -> anyhow:: Result < QueryStreamNext < T > > ;
112117 fn feed ( & mut self , index_range_response : IndexRangeResponse < T :: T > ) -> anyhow:: Result < ( ) > ;
118+
119+ /// All queries walk an index of some kind, as long as the table exists.
120+ /// This is that index name, tied to a tablet.
121+ fn tablet_index_name ( & self ) -> Option < & TabletIndexName > ;
113122}
114123
115124pub struct IndexRangeResponse < T : TableIdentifier > {
@@ -391,9 +400,12 @@ impl<RT: Runtime, T: QueryType> CompiledQuery<RT, T> {
391400 version,
392401 ) )
393402 } ,
394- QuerySource :: Search ( search) => {
395- QueryNode :: Search ( SearchQuery :: new ( search, cursor_interval, version) )
396- } ,
403+ QuerySource :: Search ( search) => QueryNode :: Search ( SearchQuery :: new (
404+ stable_index_name,
405+ search,
406+ cursor_interval,
407+ version,
408+ ) ) ,
397409 } ;
398410 for operator in query. operators {
399411 let next_node = match operator {
@@ -445,11 +457,21 @@ impl<RT: Runtime, T: QueryType> CompiledQuery<RT, T> {
445457 }
446458 }
447459
460+ pub fn fingerprint ( & self ) -> & QueryFingerprint {
461+ & self . query_fingerprint
462+ }
463+
464+ pub fn is_approaching_data_limit ( & self ) -> bool {
465+ self . root . is_approaching_data_limit ( )
466+ }
467+ }
468+
469+ impl < RT : Runtime > DeveloperQuery < RT > {
448470 pub async fn next (
449471 & mut self ,
450472 tx : & mut Transaction < RT > ,
451473 prefetch_hint : Option < usize > ,
452- ) -> anyhow:: Result < Option < GenericDocument < T :: T > > > {
474+ ) -> anyhow:: Result < Option < DeveloperDocument > > {
453475 match self . next_with_ts ( tx, prefetch_hint) . await ? {
454476 None => Ok ( None ) ,
455477 Some ( ( document, _) ) => Ok ( Some ( document) ) ,
@@ -461,32 +483,56 @@ impl<RT: Runtime, T: QueryType> CompiledQuery<RT, T> {
461483 & mut self ,
462484 tx : & mut Transaction < RT > ,
463485 prefetch_hint : Option < usize > ,
464- ) -> anyhow:: Result < Option < ( GenericDocument < T :: T > , WriteTimestamp ) > > {
486+ ) -> anyhow:: Result < Option < ( DeveloperDocument , WriteTimestamp ) > > {
465487 query_batch_next ( btreemap ! { 0 => ( self , prefetch_hint) } , tx)
466488 . await
467489 . remove ( & 0 )
468490 . context ( "batch_key missing" ) ?
469491 }
492+ }
470493
471- pub async fn expect_one (
494+ impl < RT : Runtime > ResolvedQuery < RT > {
495+ pub async fn next (
472496 & mut self ,
473497 tx : & mut Transaction < RT > ,
474- ) -> anyhow:: Result < GenericDocument < T :: T > > {
475- let v = self
476- . next ( tx, Some ( 2 ) )
477- . await ?
478- . ok_or_else ( || anyhow:: anyhow!( "Expected one value for query, received zero" ) ) ?;
498+ prefetch_hint : Option < usize > ,
499+ ) -> anyhow:: Result < Option < ResolvedDocument > > {
500+ match self . next_with_ts ( tx, prefetch_hint) . await ? {
501+ None => Ok ( None ) ,
502+ Some ( ( document, _) ) => Ok ( Some ( document) ) ,
503+ }
504+ }
479505
480- if self . next ( tx, Some ( 1 ) ) . await ?. is_some ( ) {
481- anyhow:: bail!( "Received more than one value for query" ) ;
506+ #[ convex_macro:: instrument_future]
507+ pub async fn next_with_ts (
508+ & mut self ,
509+ tx : & mut Transaction < RT > ,
510+ prefetch_hint : Option < usize > ,
511+ ) -> anyhow:: Result < Option < ( ResolvedDocument , WriteTimestamp ) > > {
512+ let tablet_id = self
513+ . root
514+ . tablet_index_name ( )
515+ . map ( |index_name| * index_name. table ( ) ) ;
516+ let result = query_batch_next ( btreemap ! { 0 => ( self , prefetch_hint) } , tx)
517+ . await
518+ . remove ( & 0 )
519+ . context ( "batch_key missing" ) ??;
520+ if let Some ( ( document, _) ) = & result {
521+ // TODO(lee) inject tablet id here which will allow the rest of the query
522+ // pipeline to use DeveloperDocuments only. To ensure this will be
523+ // correct, we do an assertion temporarily.
524+ anyhow:: ensure!(
525+ document. table( ) . table_id
526+ == tablet_id. context( "document must come from some tablet" ) ?
527+ ) ;
482528 }
483- Ok ( v )
529+ Ok ( result )
484530 }
485531
486532 pub async fn expect_at_most_one (
487533 & mut self ,
488534 tx : & mut Transaction < RT > ,
489- ) -> anyhow:: Result < Option < GenericDocument < T :: T > > > {
535+ ) -> anyhow:: Result < Option < ResolvedDocument > > {
490536 let v = match self . next ( tx, Some ( 2 ) ) . await ? {
491537 Some ( v) => v,
492538 None => return Ok ( None ) ,
@@ -496,22 +542,6 @@ impl<RT: Runtime, T: QueryType> CompiledQuery<RT, T> {
496542 }
497543 Ok ( Some ( v) )
498544 }
499-
500- pub async fn expect_none ( & mut self , tx : & mut Transaction < RT > ) -> anyhow:: Result < ( ) > {
501- anyhow:: ensure!(
502- self . next( tx, Some ( 1 ) ) . await ?. is_none( ) ,
503- "Expected no value for this query, but received one."
504- ) ;
505- Ok ( ( ) )
506- }
507-
508- pub fn fingerprint ( & self ) -> & QueryFingerprint {
509- & self . query_fingerprint
510- }
511-
512- pub fn is_approaching_data_limit ( & self ) -> bool {
513- self . root . is_approaching_data_limit ( )
514- }
515545}
516546
517547pub async fn query_batch_next < RT : Runtime , T : QueryType > (
@@ -623,6 +653,15 @@ impl<T: QueryType> QueryStream<T> for QueryNode<T> {
623653 QueryNode :: Limit ( r) => r. feed ( index_range_response) ,
624654 }
625655 }
656+
657+ fn tablet_index_name ( & self ) -> Option < & TabletIndexName > {
658+ match self {
659+ QueryNode :: IndexRange ( r) => r. tablet_index_name ( ) ,
660+ QueryNode :: Search ( r) => r. tablet_index_name ( ) ,
661+ QueryNode :: Filter ( r) => r. tablet_index_name ( ) ,
662+ QueryNode :: Limit ( r) => r. tablet_index_name ( ) ,
663+ }
664+ }
626665}
627666
628667/// Return a system limit for reading too many documents in a query
0 commit comments