11use graph:: prelude:: BlockNumber ;
22use sqlparser:: ast:: {
3- Expr , Ident , ObjectName , Query , SetExpr , Statement , TableAlias , TableFactor , VisitMut ,
4- VisitorMut ,
3+ Expr , Ident , ObjectName , Offset , Query , SetExpr , Statement , TableAlias , TableFactor , Value ,
4+ VisitMut , VisitorMut ,
55} ;
66use sqlparser:: parser:: Parser ;
77use std:: result:: Result ;
@@ -22,20 +22,30 @@ pub enum Error {
2222 NotSelectQuery ,
2323 #[ error( "Unknown table {0}" ) ]
2424 UnknownTable ( String ) ,
25+ #[ error( "Only constant numbers are supported for LIMIT and OFFSET." ) ]
26+ UnsupportedLimitOffset ,
27+ #[ error( "The limit of {0} is greater than the maximum allowed limit of {1}." ) ]
28+ UnsupportedLimit ( u32 , u32 ) ,
29+ #[ error( "The offset of {0} is greater than the maximum allowed offset of {1}." ) ]
30+ UnsupportedOffset ( u32 , u32 ) ,
2531}
2632
2733pub struct Validator < ' a > {
2834 layout : & ' a Layout ,
2935 ctes : HashSet < String > ,
3036 block : BlockNumber ,
37+ max_limit : u32 ,
38+ max_offset : u32 ,
3139}
3240
3341impl < ' a > Validator < ' a > {
34- pub fn new ( layout : & ' a Layout , block : BlockNumber ) -> Self {
42+ pub fn new ( layout : & ' a Layout , block : BlockNumber , max_limit : u32 , max_offset : u32 ) -> Self {
3543 Self {
3644 layout,
3745 ctes : Default :: default ( ) ,
3846 block,
47+ max_limit,
48+ max_offset,
3949 }
4050 }
4151
@@ -61,6 +71,45 @@ impl<'a> Validator<'a> {
6171
6272 Ok ( ( ) )
6373 }
74+
75+ pub fn validate_limit_offset ( & mut self , query : & mut Query ) -> ControlFlow < Error > {
76+ let Query { limit, offset, .. } = query;
77+
78+ if let Some ( limit) = limit {
79+ match limit {
80+ Expr :: Value ( Value :: Number ( s, _) ) => match s. parse :: < u32 > ( ) {
81+ Err ( _) => return ControlFlow :: Break ( Error :: UnsupportedLimitOffset ) ,
82+ Ok ( limit) => {
83+ if limit > self . max_limit {
84+ return ControlFlow :: Break ( Error :: UnsupportedLimit (
85+ limit,
86+ self . max_limit ,
87+ ) ) ;
88+ }
89+ }
90+ } ,
91+ _ => return ControlFlow :: Break ( Error :: UnsupportedLimitOffset ) ,
92+ }
93+ }
94+
95+ if let Some ( Offset { value, .. } ) = offset {
96+ match value {
97+ Expr :: Value ( Value :: Number ( s, _) ) => match s. parse :: < u32 > ( ) {
98+ Err ( _) => return ControlFlow :: Break ( Error :: UnsupportedLimitOffset ) ,
99+ Ok ( offset) => {
100+ if offset > self . max_offset {
101+ return ControlFlow :: Break ( Error :: UnsupportedOffset (
102+ offset,
103+ self . max_offset ,
104+ ) ) ;
105+ }
106+ }
107+ } ,
108+ _ => return ControlFlow :: Break ( Error :: UnsupportedLimitOffset ) ,
109+ }
110+ }
111+ ControlFlow :: Continue ( ( ) )
112+ }
64113}
65114
66115impl VisitorMut for Validator < ' _ > {
@@ -73,20 +122,27 @@ impl VisitorMut for Validator<'_> {
73122 }
74123 }
75124
76- fn pre_visit_query ( & mut self , _query : & mut Query ) -> ControlFlow < Self :: Break > {
125+ fn pre_visit_query ( & mut self , query : & mut Query ) -> ControlFlow < Self :: Break > {
77126 // Add common table expressions to the set of known tables
78- if let Some ( ref with) = _query . with {
127+ if let Some ( ref with) = query . with {
79128 self . ctes . extend (
80129 with. cte_tables
81130 . iter ( )
82131 . map ( |cte| cte. alias . name . value . to_lowercase ( ) ) ,
83132 ) ;
84133 }
85134
86- match * _query. body {
87- SetExpr :: Update ( _) | SetExpr :: Insert ( _) => ControlFlow :: Break ( Error :: NotSelectQuery ) ,
88- _ => ControlFlow :: Continue ( ( ) ) ,
135+ match * query. body {
136+ SetExpr :: Select ( _) | SetExpr :: Query ( _) => { /* permitted */ }
137+ SetExpr :: SetOperation { .. } => { /* permitted */ }
138+ SetExpr :: Table ( _) => { /* permitted */ }
139+ SetExpr :: Values ( _) => { /* permitted */ }
140+ SetExpr :: Insert ( _) | SetExpr :: Update ( _) => {
141+ return ControlFlow :: Break ( Error :: NotSelectQuery )
142+ }
89143 }
144+
145+ self . validate_limit_offset ( query)
90146 }
91147
92148 /// Invoked for any table function in the AST.
0 commit comments