@@ -25,6 +25,20 @@ use chrono::{NaiveDate,
25
25
} ;
26
26
27
27
use uuid:: Uuid ;
28
+ pub use self :: value:: Value ;
29
+ pub use self :: sqltype:: SQLType ;
30
+ pub use self :: table_key:: {
31
+ AlterOperation ,
32
+ TableKey ,
33
+ Key
34
+ } ;
35
+
36
+ pub use self :: sql_operator:: SQLOperator ;
37
+
38
+ mod value;
39
+ mod sqltype;
40
+ mod table_key;
41
+ mod sql_operator;
28
42
29
43
/// SQL Abstract Syntax Tree (AST)
30
44
#[ derive( Debug , Clone , PartialEq ) ]
@@ -36,7 +50,7 @@ pub enum ASTNode {
36
50
/// Multi part identifier e.g. `myschema.dbo.mytable`
37
51
SQLCompoundIdentifier ( Vec < String > ) ,
38
52
/// Assigment e.g. `name = 'Fred'` in an UPDATE statement
39
- SQLAssignment ( String , Box < ASTNode > ) ,
53
+ SQLAssignment ( SQLAssignment ) ,
40
54
/// `IS NULL` expression
41
55
SQLIsNull ( Box < ASTNode > ) ,
42
56
/// `IS NOT NULL` expression
@@ -102,7 +116,7 @@ pub enum ASTNode {
102
116
/// TABLE
103
117
table_name : String ,
104
118
/// Column assignments
105
- assignemnts : Vec < SQLAssigment > ,
119
+ assignments : Vec < SQLAssignment > ,
106
120
/// WHERE
107
121
selection : Option < Box < ASTNode > > ,
108
122
} ,
@@ -112,9 +126,6 @@ pub enum ASTNode {
112
126
relation : Option < Box < ASTNode > > ,
113
127
/// WHERE
114
128
selection : Option < Box < ASTNode > > ,
115
- /// ORDER BY
116
- order_by : Option < Vec < SQLOrderByExpr > > ,
117
- limit : Option < Box < ASTNode > > ,
118
129
} ,
119
130
/// CREATE TABLE
120
131
SQLCreateTable {
@@ -131,41 +142,134 @@ pub enum ASTNode {
131
142
}
132
143
}
133
144
134
- /// SQL values such as int, double, string timestamp
135
- #[ derive( Debug , Clone , PartialEq ) ]
136
- pub enum Value {
137
- /// Literal signed long
138
- Long ( i64 ) ,
139
- /// Literal floating point value
140
- Double ( f64 ) ,
141
- /// Unquoted string
142
- String ( String ) ,
143
- Uuid ( Uuid ) ,
144
- /// 'string value'
145
- SingleQuotedString ( String ) ,
146
- /// "string value"
147
- DoubleQuotedString ( String ) ,
148
- /// Boolean value true or false,
149
- Boolean ( bool ) ,
150
- /// Date value
151
- Date ( NaiveDate ) ,
152
- // Time
153
- Time ( NaiveTime ) ,
154
- /// Date and time
155
- DateTime ( NaiveDateTime ) ,
156
- /// Timstamp with time zone
157
- Timestamp ( DateTime < FixedOffset > ) ,
158
- /// NULL value in insert statements,
159
- Null ,
145
+
146
+ impl ToString for ASTNode {
147
+
148
+ fn to_string ( & self ) -> String {
149
+ match self {
150
+ ASTNode :: SQLIdentifier ( s) => s. to_string ( ) ,
151
+ ASTNode :: SQLWildcard => "*" . to_string ( ) ,
152
+ ASTNode :: SQLCompoundIdentifier ( s) => s. join ( "." ) ,
153
+ ASTNode :: SQLAssignment ( ass) => ass. to_string ( ) ,
154
+ ASTNode :: SQLIsNull ( ast) => format ! ( "{} IS NULL" , ast. as_ref( ) . to_string( ) ) ,
155
+ ASTNode :: SQLIsNotNull ( ast) => format ! ( "{} IS NOT NULL" , ast. as_ref( ) . to_string( ) ) ,
156
+ ASTNode :: SQLBinaryExpr { left, op, right} => {
157
+ format ! ( "{} {} {}" , left. as_ref( ) . to_string( ) , op. to_string( ) , right. as_ref( ) . to_string( ) )
158
+ }
159
+ ASTNode :: SQLCast { expr, data_type} => {
160
+ format ! ( "CAST({} AS {})" , expr. as_ref( ) . to_string( ) , data_type. to_string( ) )
161
+ }
162
+ ASTNode :: SQLNested ( ast) => format ! ( "({})" , ast. as_ref( ) . to_string( ) ) ,
163
+ ASTNode :: SQLUnary { operator, rex } => {
164
+ format ! ( "{} {}" , operator. to_string( ) , rex. as_ref( ) . to_string( ) )
165
+ }
166
+ ASTNode :: SQLValue ( v) => v. to_string ( ) ,
167
+ ASTNode :: SQLFunction { id, args} => format ! ( "{}({})" , id, args. iter( ) . map( |a|a. to_string( ) ) . collect:: <Vec <String >>( ) . join( ", " ) ) ,
168
+ ASTNode :: SQLSelect {
169
+ projection,
170
+ relation,
171
+ selection,
172
+ order_by,
173
+ group_by,
174
+ having,
175
+ limit,
176
+ } => {
177
+ let mut s = format ! ( "SELECT {}" , projection. iter( ) . map( |p|p. to_string( ) ) . collect:: <Vec <String >>( ) . join( ", " ) ) ;
178
+ if let Some ( relation) = relation{
179
+ s += & format ! ( " FROM {}" , relation. as_ref( ) . to_string( ) ) ;
180
+ }
181
+ if let Some ( selection) = selection{
182
+ s += & format ! ( " WHERE {}" , selection. as_ref( ) . to_string( ) ) ;
183
+ }
184
+ if let Some ( group_by) = group_by {
185
+ s += & format ! ( " GROUP BY {}" , group_by. iter( ) . map( |g|g. to_string( ) ) . collect:: <Vec <String >>( ) . join( ", " ) ) ;
186
+ }
187
+ if let Some ( having) = having{
188
+ s += & format ! ( " HAVING {}" , having. as_ref( ) . to_string( ) ) ;
189
+ }
190
+ if let Some ( order_by) = order_by{
191
+ s += & format ! ( " ORDER BY {}" , order_by. iter( ) . map( |o|o. to_string( ) ) . collect:: <Vec <String >>( ) . join( ", " ) ) ;
192
+ }
193
+ if let Some ( limit) = limit {
194
+ s += & format ! ( " LIMIT {}" , limit. as_ref( ) . to_string( ) ) ;
195
+ }
196
+ s
197
+ }
198
+ ASTNode :: SQLInsert { table_name, columns, values } => {
199
+ let mut s = format ! ( "INSERT INTO {}" , table_name) ;
200
+ if columns. len ( ) > 0 {
201
+ s += & format ! ( " ({})" , columns. join( ", " ) ) ;
202
+ }
203
+ if values. len ( ) > 0 {
204
+ s += & format ! ( " VALUES({})" ,
205
+ values. iter( )
206
+ . map( |row|row. iter( ) . map( |c|c. to_string( ) )
207
+ . collect:: <Vec <String >>( ) . join( ", " )
208
+ ) . collect:: <Vec <String >>( ) . join( ", " )
209
+ ) ;
210
+ }
211
+ s
212
+ }
213
+ ASTNode :: SQLCopy { table_name, columns, values} => {
214
+ let mut s = format ! ( "COPY {}" , table_name) ;
215
+ if columns. len ( ) > 0 {
216
+ s += & format ! ( " ({})" , columns. iter( ) . map( |c|c. to_string( ) ) . collect:: <Vec <String >>( ) . join( ", " ) ) ;
217
+ }
218
+ s += " FROM stdin; " ;
219
+ if values. len ( ) > 0 {
220
+ s += & format ! ( "\n {}" ,
221
+ values. iter( )
222
+ . map( |v|v. to_string( ) )
223
+ . collect:: <Vec <String >>( ) . join( "\t " )
224
+ ) ;
225
+ }
226
+ s
227
+ }
228
+ ASTNode :: SQLUpdate { table_name, assignments, selection} => {
229
+ let mut s = format ! ( "UPDATE {}" , table_name) ;
230
+ if assignments. len ( ) > 0 {
231
+ s += & format ! ( "{}" , assignments. iter( ) . map( |ass|ass. to_string( ) ) . collect:: <Vec <String >>( ) . join( ", " ) ) ;
232
+ }
233
+ if let Some ( selection) = selection{
234
+ s += & format ! ( " WHERE {}" , selection. as_ref( ) . to_string( ) ) ;
235
+ }
236
+ s
237
+ }
238
+ ASTNode :: SQLDelete { relation, selection} => {
239
+ let mut s = String :: from ( "DELETE" ) ;
240
+ if let Some ( relation) = relation{
241
+ s += & format ! ( " FROM {}" , relation. as_ref( ) . to_string( ) ) ;
242
+ }
243
+ if let Some ( selection) = selection{
244
+ s += & format ! ( " WHERE {}" , selection. as_ref( ) . to_string( ) ) ;
245
+ }
246
+ s
247
+ }
248
+ ASTNode :: SQLCreateTable { name, columns} => {
249
+ format ! ( "CREATE TABLE {} ({})" , name, columns. iter( ) . map( |c|c. to_string( ) ) . collect:: <Vec <String >>( ) . join( ", " ) )
250
+ }
251
+ ASTNode :: SQLAlterTable { name, operation} => {
252
+ format ! ( "ALTER TABLE {} {}" , name, operation. to_string( ) )
253
+ }
254
+ }
255
+ }
160
256
}
161
257
162
258
/// SQL assignment `foo = expr` as used in SQLUpdate
259
+ /// TODO: unify this with the ASTNode SQLAssignment
163
260
#[ derive( Debug , Clone , PartialEq ) ]
164
- pub struct SQLAssigment {
261
+ pub struct SQLAssignment {
165
262
id : String ,
166
263
value : Box < ASTNode > ,
167
264
}
168
265
266
+ impl ToString for SQLAssignment {
267
+
268
+ fn to_string ( & self ) -> String {
269
+ format ! ( "SET {} = {}" , self . id, self . value. as_ref( ) . to_string( ) )
270
+ }
271
+ }
272
+
169
273
/// SQL ORDER BY expression
170
274
#[ derive( Debug , Clone , PartialEq ) ]
171
275
pub struct SQLOrderByExpr {
@@ -179,109 +283,45 @@ impl SQLOrderByExpr {
179
283
}
180
284
}
181
285
286
+ impl ToString for SQLOrderByExpr {
287
+ fn to_string ( & self ) -> String {
288
+ if self . asc {
289
+ format ! ( "{} ASC" , self . expr. as_ref( ) . to_string( ) )
290
+ } else {
291
+ format ! ( "{} DESC" , self . expr. as_ref( ) . to_string( ) )
292
+ }
293
+ }
294
+ }
295
+
182
296
/// SQL column definition
183
297
#[ derive( Debug , Clone , PartialEq ) ]
184
298
pub struct SQLColumnDef {
185
299
pub name : String ,
186
300
pub data_type : SQLType ,
187
- pub allow_null : bool ,
188
301
pub is_primary : bool ,
189
302
pub is_unique : bool ,
190
303
pub default : Option < Box < ASTNode > > ,
304
+ pub allow_null : bool ,
191
305
}
192
306
193
- /// SQL datatypes for literals in SQL statements
194
- #[ derive( Debug , Clone , PartialEq ) ]
195
- pub enum SQLType {
196
- /// Fixed-length character type e.g. CHAR(10)
197
- Char ( Option < usize > ) ,
198
- /// Variable-length character type e.g. VARCHAR(10)
199
- Varchar ( Option < usize > ) ,
200
- /// Uuid value
201
- Uuid ,
202
- /// Large character object e.g. CLOB(1000)
203
- Clob ( usize ) ,
204
- /// Fixed-length binary type e.g. BINARY(10)
205
- Binary ( usize ) ,
206
- /// Variable-length binary type e.g. VARBINARY(10)
207
- Varbinary ( usize ) ,
208
- /// Large binary object e.g. BLOB(1000)
209
- Blob ( usize ) ,
210
- /// Decimal type with precision and optional scale e.g. DECIMAL(10,2)
211
- Decimal ( usize , Option < usize > ) ,
212
- /// Small integer
213
- SmallInt ,
214
- /// Integer
215
- Int ,
216
- /// Big integer
217
- BigInt ,
218
- /// Floating point with optional precision e.g. FLOAT(8)
219
- Float ( Option < usize > ) ,
220
- /// Floating point e.g. REAL
221
- Real ,
222
- /// Double e.g. DOUBLE PRECISION
223
- Double ,
224
- /// Boolean
225
- Boolean ,
226
- /// Date
227
- Date ,
228
- /// Time
229
- Time ,
230
- /// Timestamp
231
- Timestamp ,
232
- /// Regclass used in postgresql serial
233
- Regclass ,
234
- /// Text
235
- Text ,
236
- /// Bytea
237
- Bytea ,
238
- /// Custom type such as enums
239
- Custom ( String ) ,
240
- /// Arrays
241
- Array ( Box < SQLType > ) ,
242
- }
243
307
244
- /// SQL Operator
245
- #[ derive( Debug , PartialEq , Clone ) ]
246
- pub enum SQLOperator {
247
- Plus ,
248
- Minus ,
249
- Multiply ,
250
- Divide ,
251
- Modulus ,
252
- Gt ,
253
- Lt ,
254
- GtEq ,
255
- LtEq ,
256
- Eq ,
257
- NotEq ,
258
- And ,
259
- Or ,
260
- }
308
+ impl ToString for SQLColumnDef {
261
309
262
- #[ derive( Debug , PartialEq , Clone ) ]
263
- pub enum AlterOperation {
264
- AddConstraint ( TableKey ) ,
265
- RemoveConstraint {
266
- name : String ,
310
+ fn to_string ( & self ) -> String {
311
+ let mut s = format ! ( "{} {}" , self . name, self . data_type. to_string( ) ) ;
312
+ if self . is_primary {
313
+ s += " PRIMARY KEY" ;
314
+ }
315
+ if self . is_unique {
316
+ s += " UNIQUE" ;
317
+ }
318
+ if let Some ( ref default) = self . default {
319
+ s += & format ! ( " DEFAULT {}" , default . as_ref( ) . to_string( ) ) ;
320
+ }
321
+ if !self . allow_null {
322
+ s += " NOT NULL" ;
323
+ }
324
+ s
267
325
}
268
326
}
269
327
270
-
271
- #[ derive( Debug , PartialEq , Clone ) ]
272
- pub struct Key {
273
- pub name : Option < String > ,
274
- pub columns : Vec < String > ,
275
- }
276
-
277
- #[ derive( Debug , PartialEq , Clone ) ]
278
- pub enum TableKey {
279
- PrimaryKey ( Key ) ,
280
- UniqueKey ( Key ) ,
281
- Key ( Key ) ,
282
- ForeignKey {
283
- key : Key ,
284
- foreign_table : String ,
285
- referred_columns : Vec < String > ,
286
- }
287
- }
0 commit comments