@@ -35,21 +35,18 @@ impl Cursor {
3535 Cursor ( map)
3636 }
3737
38- pub fn from_chains ( chains : & HashSet < u64 > ) -> Self {
39- let map = chains. iter ( ) . map ( |& c| ( c, None ) ) . collect ( ) ;
40- Cursor ( map)
38+ pub fn add_chains ( & mut self , chains : & HashSet < u64 > ) {
39+ chains. iter ( ) . for_each ( |& c| {
40+ self . 0 . entry ( c) . or_insert ( None ) ;
41+ } )
4142 }
4243
4344 pub fn contains ( & self , chain : u64 ) -> bool {
4445 self . 0 . keys ( ) . any ( |c| * c == chain)
4546 }
4647
4748 pub fn chains ( & self ) -> Vec < u64 > {
48- self . 0 . keys ( ) . cloned ( ) . collect ( )
49- }
50-
51- pub fn set_block_height ( & mut self , chain : u64 , n : u64 ) {
52- self . 0 . insert ( chain, Some ( n) ) ;
49+ self . 0 . keys ( ) . sorted ( ) . cloned ( ) . collect ( )
5350 }
5451
5552 pub fn chain ( & self ) -> u64 {
@@ -59,36 +56,42 @@ impl Cursor {
5956 }
6057 }
6158
62- pub fn to_sql ( & self ) -> String {
63- self . 0
59+ pub fn set_block_height ( & mut self , chain : u64 , n : u64 ) {
60+ self . 0 . insert ( chain, Some ( n) ) ;
61+ }
62+
63+ pub fn to_sql ( & self , col_name : & str ) -> String {
64+ let predicates = self
65+ . 0
6466 . iter ( )
67+ . sorted_by_key ( |( chain, _) | * chain)
6568 . map ( |( chain, block_num) | match block_num {
66- Some ( n) => format ! ( "(chain = {} and block_num > {})" , chain, n) ,
69+ Some ( n) => format ! ( "(chain = {} and {} > {})" , chain, col_name , n) ,
6770 None => format ! ( "chain = {}" , chain) ,
6871 } )
69- . collect :: < Vec < _ > > ( )
70- . join ( " or " )
72+ . collect :: < Vec < _ > > ( ) ;
73+ if predicates. len ( ) == 1 {
74+ predicates[ 0 ] . clone ( )
75+ } else {
76+ format ! ( "({})" , predicates. join( " or " ) )
77+ }
7178 }
7279}
7380
74- pub struct EnhancedQuery {
75- pub query : String ,
76- pub cusror : Cursor ,
77- }
78-
7981const PG : & sqlparser:: dialect:: PostgreSqlDialect = & sqlparser:: dialect:: PostgreSqlDialect { } ;
8082
8183/// Parses the user supplied query into a SQL AST
8284/// and validates the query against the provided event signatures.
8385/// The SQL API implements onlny a subset of SQL so un-supported
8486/// SQL results in an error.
8587pub fn sql (
86- cursor : Option < Cursor > ,
88+ cursor : & mut Cursor ,
8789 signatures : Vec < & str > ,
8890 user_query : & str ,
89- ) -> Result < EnhancedQuery , api:: Error > {
91+ ) -> Result < String , api:: Error > {
9092 let mut q = UserQuery :: new ( signatures) ?;
91- let new_query = q. process ( user_query) ?;
93+ let rewritten_query = q. process ( user_query) ?;
94+ cursor. add_chains ( & q. chains ) ;
9295 let query = [
9396 "with" . to_string ( ) ,
9497 q. relations
@@ -97,13 +100,10 @@ pub fn sql(
97100 . sorted_by_key ( |s| s. table_name . to_string ( ) )
98101 . map ( |rel| rel. to_sql ( cursor. clone ( ) ) )
99102 . join ( "," ) ,
100- new_query . to_string ( ) ,
103+ rewritten_query . to_string ( ) ,
101104 ]
102105 . join ( " " ) ;
103- Ok ( EnhancedQuery {
104- query,
105- cusror : Cursor :: from_chains ( & q. chains ) ,
106- } )
106+ Ok ( query)
107107}
108108
109109/*
@@ -153,7 +153,7 @@ impl Relation {
153153 || self . table_alias . contains ( other)
154154 }
155155
156- fn to_sql ( & self , cursor : Option < Cursor > ) -> String {
156+ fn to_sql ( & self , cursor : Cursor ) -> String {
157157 let mut res: Vec < String > = Vec :: new ( ) ;
158158 res. push ( format ! ( "{} as not materialized (" , self . table_name) ) ;
159159 res. push ( "select" . to_string ( ) ) ;
@@ -182,8 +182,10 @@ impl Relation {
182182 res. push ( select_list. join ( "," ) ) ;
183183
184184 let mut predicates = vec ! [ ] ;
185- if let Some ( cursor) = cursor {
186- predicates. push ( cursor. to_sql ( ) ) ;
185+ if self . table_name . value . to_lowercase ( ) == "blocks" {
186+ predicates. push ( cursor. to_sql ( "num" ) ) ;
187+ } else {
188+ predicates. push ( cursor. to_sql ( "block_num" ) ) ;
187189 }
188190 if let Some ( event) = self . event . as_ref ( ) {
189191 predicates. push ( event. sighash_sql_predicate ( ) ) ;
@@ -950,10 +952,10 @@ mod tests {
950952 }
951953
952954 async fn check_sql ( event_sigs : Vec < & str > , user_query : & str , want : & str ) {
953- let got = sql ( Some ( Cursor :: new ( 1 , None ) ) , event_sigs, user_query)
955+ let got = sql ( & mut Cursor :: new ( 1 , None ) , event_sigs, user_query)
954956 . unwrap_or_else ( |e| panic ! ( "unable to create sql for:\n {} error: {:?}" , user_query, e) ) ;
955957 let ( got, want) = (
956- fmt_sql ( & got. query ) . unwrap_or_else ( |_| panic ! ( "unable to format got: {}" , got. query ) ) ,
958+ fmt_sql ( & got) . unwrap_or_else ( |_| panic ! ( "unable to format got: {}" , got) ) ,
957959 fmt_sql ( want) . unwrap_or_else ( |_| panic ! ( "unable to format want: {}" , want) ) ,
958960 ) ;
959961 if got. to_lowercase ( ) . ne ( & want. to_lowercase ( ) ) {
@@ -964,6 +966,24 @@ mod tests {
964966 pg. query ( & got, & [ ] ) . await . expect ( "issue with query" ) ;
965967 }
966968
969+ #[ test]
970+ fn test_cursor ( ) {
971+ let mut cursor = Cursor :: default ( ) ;
972+ cursor. set_block_height ( 8453 , 100 ) ;
973+ cursor. set_block_height ( 10 , 42 ) ;
974+ let _ = sql (
975+ & mut cursor,
976+ vec ! [ ] ,
977+ "select hash from txs where chain in (8453, 10, 1)" ,
978+ )
979+ . unwrap ( ) ;
980+ assert_eq ! ( cursor. chains( ) , vec![ 1 , 10 , 8453 ] ) ;
981+ assert_eq ! (
982+ cursor. to_sql( "foo" ) ,
983+ "(chain = 1 or (chain = 10 and foo > 42) or (chain = 8453 and foo > 100))"
984+ ) ;
985+ }
986+
967987 #[ tokio:: test]
968988 async fn test_blocks_table ( ) {
969989 check_sql (
0 commit comments