@@ -4,12 +4,8 @@ use clap_verbosity_flag::{InfoLevel, Verbosity};
4
4
use env_logger:: Builder ;
5
5
use log:: info;
6
6
use poise:: serenity_prelude as serenity;
7
+ use regex:: Regex ;
7
8
use reqwest:: { Client , Response } ;
8
- use sqlparser:: ast:: FormatClause :: Identifier ;
9
- use sqlparser:: ast:: Statement :: Query ;
10
- use sqlparser:: ast:: { Expr , Ident , Value } ;
11
- use sqlparser:: dialect:: ClickHouseDialect ;
12
- use sqlparser:: parser:: Parser as SqlParser ;
13
9
use std:: io:: Write ;
14
10
use tabled:: settings:: Style ;
15
11
use url:: { ParseError , Url } ;
@@ -69,49 +65,39 @@ async fn format_url(cli: &CLI) -> Result<String, ParseError> {
69
65
Ok ( url. join ( & qs) ?. to_string ( ) )
70
66
}
71
67
72
- async fn format_query ( query : String , output_limit : String ) -> Result < String , Error > {
73
- let dialect = ClickHouseDialect { } ;
74
- let ast = SqlParser :: parse_sql ( & dialect, & query) ?;
75
- if ast. len ( ) != 1 {
76
- return Err ( ( ) ) . map_err ( |_| "Only one query is allowed" . into ( ) ) ;
77
- }
78
- let mut statement = ast[ 0 ] . clone ( ) ;
79
-
80
- // Check if the query has a limit clause
81
- // If it does, check if the limit is greater than the output limit
82
- // If it is, set the limit to the output limit
83
- match statement {
84
- Query ( ref mut query) => match & query. limit {
85
- Some ( Expr :: Value ( Value :: Number ( limit, b) ) ) => {
86
- let limit: i32 = limit. parse ( ) . unwrap ( ) ;
87
- let output_limit = match output_limit. parse ( ) {
88
- Ok ( output_limit) => output_limit,
89
- Err ( _) => return Err ( ( ) ) . map_err ( |_| "Invalid output limit" . into ( ) ) ,
90
- } ;
91
- if limit > output_limit {
92
- query. limit = Some ( Expr :: Value ( Value :: Number ( output_limit. to_string ( ) , * b) ) ) ;
93
- }
94
- }
95
- None => {
96
- query. limit = Some ( Expr :: Value ( Value :: Number ( output_limit. to_string ( ) , false ) ) ) ;
97
- }
98
- _ => { }
99
- } ,
100
- _ => { }
101
- } ;
68
+ async fn format_query ( query : String , output_limit : i32 ) -> Result < String , Error > {
69
+ let mut formatted_query = query. clone ( ) ;
102
70
103
- // Set the format clause to CSVWithNames
104
- match statement {
105
- Query ( ref mut query) => {
106
- query. format_clause = Some ( Identifier ( Ident {
107
- value : "CSVWithNames" . to_string ( ) ,
108
- quote_style : None ,
109
- } ) ) ;
71
+ let re = Regex :: new ( r".*LIMIT\s(\d+).*$" ) . unwrap ( ) ;
72
+ let limit: Option < i32 > = match re. captures ( & query) {
73
+ Some ( caps) => Some ( caps. get ( 1 ) . unwrap ( ) . as_str ( ) . parse ( ) . unwrap ( ) ) ,
74
+ None => None ,
75
+ } ;
76
+ if let Some ( limit) = limit {
77
+ if limit > output_limit {
78
+ formatted_query = query. replace (
79
+ & format ! ( "LIMIT {}" , limit) ,
80
+ & format ! ( "LIMIT {}" , output_limit) ,
81
+ ) ;
110
82
}
111
- _ => { }
83
+ } else {
84
+ formatted_query = format ! ( "{} LIMIT {}" , query, output_limit)
85
+ }
86
+
87
+ let re = Regex :: new ( r".*FORMAT\s(\S+).*$" ) . unwrap ( ) ;
88
+ let format: Option < String > = match re. captures ( & formatted_query) {
89
+ Some ( caps) => Some ( caps. get ( 1 ) . unwrap ( ) . as_str ( ) . to_string ( ) ) ,
90
+ None => None ,
112
91
} ;
92
+ if let Some ( format) = format {
93
+ if format != "CSVWithNames" {
94
+ formatted_query = formatted_query. replace ( & format, "CSVWithNames" ) ;
95
+ }
96
+ } else {
97
+ formatted_query = format ! ( "{} FORMAT CSVWithNames" , formatted_query)
98
+ }
113
99
114
- Ok ( statement . to_string ( ) )
100
+ Ok ( formatted_query )
115
101
}
116
102
117
103
async fn do_query ( query : String , url : String ) -> Result < Response , Error > {
@@ -148,7 +134,8 @@ async fn query(
148
134
}
149
135
} ;
150
136
151
- let query_text = match format_query ( query_text, ctx. data ( ) . output_limit . clone ( ) ) . await {
137
+ let output_limit: i32 = ctx. data ( ) . output_limit . clone ( ) . parse ( ) . unwrap ( ) ;
138
+ let query_text = match format_query ( query_text, output_limit) . await {
152
139
Ok ( query_text) => query_text,
153
140
Err ( e) => {
154
141
ctx. say ( format ! ( "{}" , e) ) . await ?;
@@ -201,19 +188,16 @@ mod tests {
201
188
#[ tokio:: test]
202
189
async fn test_format_query ( ) {
203
190
assert_eq ! (
204
- format_query(
205
- "SELECT Count() FROM nxthdr.bgp_updates" . to_string( ) ,
206
- "10" . to_string( )
207
- )
208
- . await
209
- . unwrap( ) ,
191
+ format_query( "SELECT Count() FROM nxthdr.bgp_updates" . to_string( ) , 10 )
192
+ . await
193
+ . unwrap( ) ,
210
194
"SELECT Count() FROM nxthdr.bgp_updates LIMIT 10 FORMAT CSVWithNames" . to_string( )
211
195
) ;
212
196
213
197
assert_eq ! (
214
198
format_query(
215
199
"SELECT Count() FROM nxthdr.bgp_updates LIMIT 5" . to_string( ) ,
216
- "10" . to_string ( )
200
+ 10
217
201
)
218
202
. await
219
203
. unwrap( ) ,
@@ -223,7 +207,7 @@ mod tests {
223
207
assert_eq ! (
224
208
format_query(
225
209
"SELECT Count() FROM nxthdr.bgp_updates LIMIT 50" . to_string( ) ,
226
- "10" . to_string ( )
210
+ 10
227
211
)
228
212
. await
229
213
. unwrap( ) ,
@@ -233,7 +217,7 @@ mod tests {
233
217
assert_eq ! (
234
218
format_query(
235
219
"SELECT Count() FROM nxthdr.bgp_updates LIMIT 50 FORMAT Pretty" . to_string( ) ,
236
- "10" . to_string ( )
220
+ 10
237
221
)
238
222
. await
239
223
. unwrap( ) ,
0 commit comments