@@ -4,7 +4,7 @@ use readyset_util::fmt::fmt_with;
4
4
use serde:: { Deserialize , Serialize } ;
5
5
use test_strategy:: Arbitrary ;
6
6
7
- use crate :: { ast:: * , Dialect , DialectDisplay } ;
7
+ use crate :: { ast:: * , AstConversionError , Dialect , DialectDisplay } ;
8
8
9
9
#[ derive( Clone , Debug , Eq , Hash , PartialEq , Serialize , Deserialize , Arbitrary ) ]
10
10
pub struct Column {
@@ -33,6 +33,66 @@ impl From<&'_ str> for Column {
33
33
}
34
34
}
35
35
36
+ impl From < sqlparser:: ast:: Ident > for Column {
37
+ fn from ( value : sqlparser:: ast:: Ident ) -> Self {
38
+ Self {
39
+ name : value. into ( ) ,
40
+ table : None ,
41
+ }
42
+ }
43
+ }
44
+
45
+ impl From < Vec < sqlparser:: ast:: Ident > > for Column {
46
+ fn from ( mut value : Vec < sqlparser:: ast:: Ident > ) -> Self {
47
+ let name: SqlIdentifier = value. pop ( ) . unwrap ( ) . into ( ) ;
48
+ let table = if let Some ( table) = value. pop ( ) {
49
+ if let Some ( schema) = value. pop ( ) {
50
+ Some ( Relation {
51
+ schema : Some ( schema. into ( ) ) ,
52
+ name : table. into ( ) ,
53
+ } )
54
+ } else {
55
+ Some ( Relation {
56
+ schema : None ,
57
+ name : table. into ( ) ,
58
+ } )
59
+ }
60
+ } else {
61
+ None
62
+ } ;
63
+ Self { name, table }
64
+ }
65
+ }
66
+
67
+ impl From < sqlparser:: ast:: ObjectName > for Column {
68
+ fn from ( value : sqlparser:: ast:: ObjectName ) -> Self {
69
+ value
70
+ . 0
71
+ . into_iter ( )
72
+ . map ( |sqlparser:: ast:: ObjectNamePart :: Identifier ( ident) | ident)
73
+ . collect :: < Vec < _ > > ( )
74
+ . into ( )
75
+ }
76
+ }
77
+
78
+ impl From < sqlparser:: ast:: ViewColumnDef > for Column {
79
+ fn from ( value : sqlparser:: ast:: ViewColumnDef ) -> Self {
80
+ Self {
81
+ name : value. name . into ( ) ,
82
+ table : None ,
83
+ }
84
+ }
85
+ }
86
+
87
+ impl From < sqlparser:: ast:: AssignmentTarget > for Column {
88
+ fn from ( value : sqlparser:: ast:: AssignmentTarget ) -> Self {
89
+ match value {
90
+ sqlparser:: ast:: AssignmentTarget :: ColumnName ( object_name) => object_name. into ( ) ,
91
+ sqlparser:: ast:: AssignmentTarget :: Tuple ( _vec) => todo ! ( "tuple assignment syntax" ) ,
92
+ }
93
+ }
94
+ }
95
+
36
96
impl Ord for Column {
37
97
fn cmp ( & self , other : & Column ) -> Ordering {
38
98
match ( self . table . as_ref ( ) , other. table . as_ref ( ) ) {
@@ -120,6 +180,105 @@ pub struct ColumnSpecification {
120
180
pub comment : Option < String > ,
121
181
}
122
182
183
+ impl TryFrom < sqlparser:: ast:: ColumnDef > for ColumnSpecification {
184
+ type Error = AstConversionError ;
185
+
186
+ fn try_from ( value : sqlparser:: ast:: ColumnDef ) -> Result < Self , Self :: Error > {
187
+ use sqlparser:: {
188
+ keywords:: Keyword ,
189
+ tokenizer:: { Token , Word } ,
190
+ } ;
191
+
192
+ let mut comment = None ;
193
+ let mut constraints = vec ! [ ] ;
194
+ let mut generated = None ;
195
+ for option in value. options {
196
+ match option. option {
197
+ sqlparser:: ast:: ColumnOption :: Null => constraints. push ( ColumnConstraint :: Null ) ,
198
+ sqlparser:: ast:: ColumnOption :: NotNull => {
199
+ constraints. push ( ColumnConstraint :: NotNull )
200
+ }
201
+ sqlparser:: ast:: ColumnOption :: Default ( expr) => {
202
+ constraints. push ( ColumnConstraint :: DefaultValue ( expr. try_into ( ) ?) )
203
+ }
204
+ sqlparser:: ast:: ColumnOption :: Unique {
205
+ is_primary,
206
+ characteristics,
207
+ } => {
208
+ if characteristics. is_some ( ) {
209
+ return not_yet_implemented ! ( "constraint timing on column definitions" ) ;
210
+ } else if is_primary {
211
+ constraints. push ( ColumnConstraint :: PrimaryKey )
212
+ } else {
213
+ constraints. push ( ColumnConstraint :: Unique )
214
+ }
215
+ }
216
+ sqlparser:: ast:: ColumnOption :: ForeignKey { .. } => {
217
+ return not_yet_implemented ! ( "foreign key" ) ;
218
+ }
219
+ sqlparser:: ast:: ColumnOption :: DialectSpecific ( vec) => {
220
+ if vec. iter ( ) . any ( |token| {
221
+ matches ! (
222
+ token,
223
+ Token :: Word ( Word {
224
+ keyword: Keyword :: AUTO_INCREMENT ,
225
+ ..
226
+ } )
227
+ )
228
+ } ) {
229
+ constraints. push ( ColumnConstraint :: AutoIncrement )
230
+ }
231
+ }
232
+ sqlparser:: ast:: ColumnOption :: CharacterSet ( object_name) => {
233
+ constraints. push ( ColumnConstraint :: CharacterSet ( object_name. to_string ( ) ) )
234
+ }
235
+ sqlparser:: ast:: ColumnOption :: Collation ( object_name) => {
236
+ constraints. push ( ColumnConstraint :: Collation ( object_name. to_string ( ) ) )
237
+ }
238
+ sqlparser:: ast:: ColumnOption :: Comment ( s) => {
239
+ comment = Some ( s) ;
240
+ }
241
+ sqlparser:: ast:: ColumnOption :: OnUpdate ( _expr) => {
242
+ todo ! ( "on update (check for current_timestamp)" )
243
+ }
244
+ sqlparser:: ast:: ColumnOption :: Generated {
245
+ generated_as : _,
246
+ sequence_options : _,
247
+ generation_expr,
248
+ generation_expr_mode,
249
+ generated_keyword : _,
250
+ } => {
251
+ generated = Some ( GeneratedColumn {
252
+ expr : generation_expr
253
+ . map ( TryInto :: try_into)
254
+ . expect ( "generated expr can't be None" ) ?,
255
+ stored : generation_expr_mode
256
+ == Some ( sqlparser:: ast:: GeneratedExpressionMode :: Stored ) ,
257
+ } )
258
+ }
259
+ sqlparser:: ast:: ColumnOption :: Materialized ( _)
260
+ | sqlparser:: ast:: ColumnOption :: Ephemeral ( _)
261
+ | sqlparser:: ast:: ColumnOption :: Alias ( _)
262
+ | sqlparser:: ast:: ColumnOption :: Check ( _)
263
+ | sqlparser:: ast:: ColumnOption :: Options ( _)
264
+ | sqlparser:: ast:: ColumnOption :: Identity ( _)
265
+ | sqlparser:: ast:: ColumnOption :: OnConflict ( _)
266
+ | sqlparser:: ast:: ColumnOption :: Policy ( _)
267
+ | sqlparser:: ast:: ColumnOption :: Tags ( _) => {
268
+ // Don't care about these options
269
+ }
270
+ }
271
+ }
272
+ Ok ( Self {
273
+ column : value. name . into ( ) ,
274
+ sql_type : value. data_type . try_into ( ) ?,
275
+ constraints,
276
+ comment,
277
+ generated,
278
+ } )
279
+ }
280
+ }
281
+
123
282
impl ColumnSpecification {
124
283
pub fn new ( column : Column , sql_type : SqlType ) -> ColumnSpecification {
125
284
ColumnSpecification {
0 commit comments