@@ -2,7 +2,7 @@ use std::fmt;
22use std:: str:: FromStr ;
33
44use async_recursion:: async_recursion;
5- use heck:: AsUpperCamelCase ;
5+ use heck:: { AsUpperCamelCase , AsSnakeCase } ;
66use tokio_postgres:: types:: { ToSql , Type as PgType } ;
77use tokio_postgres:: Client ;
88
@@ -156,15 +156,69 @@ impl fmt::Display for Type {
156156 }
157157}
158158
159+ #[ derive( Debug ) ]
160+ pub enum TypeDefinition {
161+ Composite ( Composite ) ,
162+ Enum ( Enum ) ,
163+ }
164+
165+ impl fmt:: Display for TypeDefinition {
166+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
167+ match self {
168+ Self :: Composite ( inner) => f. write_fmt ( format_args ! ( "{inner}" ) ) ,
169+ Self :: Enum ( inner) => f. write_fmt ( format_args ! ( "{inner}" ) ) ,
170+ }
171+ }
172+ }
173+
174+ #[ derive( Debug ) ]
175+ pub struct Composite {
176+ pub name : String ,
177+ pub fields : Vec < ( String , Type ) > ,
178+ }
179+
180+ impl Composite {
181+ pub ( crate ) async fn from_postgres (
182+ name : & str ,
183+ client : & Client ,
184+ ) -> Result < Self , tokio_postgres:: Error > {
185+ let sql = "SELECT attname, atttypid
186+ FROM pg_type, pg_attribute
187+ WHERE typname = $1 AND pg_type.typrelid = pg_attribute.attrelid" ;
188+
189+ let mut fields = Vec :: new ( ) ;
190+ for row in client. query ( sql, & [ & name] ) . await ? {
191+ let name = row. get :: < _ , & str > ( 0 ) ;
192+ let r#type = Type :: from_postgres_by_id ( row. get ( 1 ) , client) . await ?;
193+ fields. push ( ( name. to_owned ( ) , r#type) ) ;
194+ }
195+
196+ Ok ( Self {
197+ name : name. to_owned ( ) ,
198+ fields,
199+ } )
200+ }
201+ }
202+
203+ impl fmt:: Display for Composite {
204+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
205+ f. write_fmt ( format_args ! ( "struct {} {{\n " , AsUpperCamelCase ( & self . name) ) ) ?;
206+ for ( name, ty) in & self . fields {
207+ f. write_fmt ( format_args ! ( " {}: {ty},\n " , AsSnakeCase ( & name) ) ) ?;
208+ }
209+
210+ f. write_str ( "}\n " )
211+ }
212+ }
213+
159214#[ derive( Debug , PartialEq ) ]
160- pub struct PgEnum {
215+ pub struct Enum {
161216 name : String ,
162217 variants : Vec < String > ,
163218}
164219
165- impl PgEnum {
166- async fn from_postgres (
167- id : u32 ,
220+ impl Enum {
221+ pub ( crate ) async fn from_postgres (
168222 name : & str ,
169223 client : & Client ,
170224 ) -> Result < Self , tokio_postgres:: Error > {
@@ -175,11 +229,11 @@ impl PgEnum {
175229
176230 let sql = r#"
177231 SELECT enumlabel
178- FROM pg_catalog.pg_enum
179- WHERE enumtypid = $1
232+ FROM pg_catalog.pg_enum, pg_catalog.pg_type
233+ WHERE pg_type.typname = $1 AND pg_type.oid = enumtypid
180234 ORDER BY enumsortorder ASC
181235 "# ;
182- for row in client. query ( sql, & [ & id ] ) . await ? {
236+ for row in client. query ( sql, & [ & name ] ) . await ? {
183237 let label = row. get :: < _ , & str > ( 0 ) ;
184238 new. variants . push ( label. to_owned ( ) ) ;
185239 }
@@ -188,11 +242,11 @@ impl PgEnum {
188242 }
189243}
190244
191- impl fmt:: Display for PgEnum {
245+ impl fmt:: Display for Enum {
192246 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
193247 f. write_fmt ( format_args ! ( "enum {} {{\n " , AsUpperCamelCase ( & self . name) ) ) ?;
194248 for variant in & self . variants {
195- f. write_fmt ( format_args ! ( " {}," , AsUpperCamelCase ( & variant) ) ) ?;
249+ f. write_fmt ( format_args ! ( " {},\n " , AsUpperCamelCase ( & variant) ) ) ?;
196250 }
197251
198252 f. write_str ( "}\n " )
0 commit comments