33import dbd
44import os
55from argparse import ArgumentParser
6+ from collections import defaultdict
67from glob import glob
78
89script_dir :str = os .path .dirname (os .path .abspath (__file__ ));
@@ -67,27 +68,32 @@ def get_sql_type(type:str, int_width:int=0, is_unsigned:bool=False)->str:
6768
6869 return f"{ type } DEFAULT { default } " ;
6970
70- file : str
71- for file in dbds :
71+ keys : dict [ str , dict [ str , str ]] = defaultdict ( dict );
72+ def process_dbd ( file : str ) -> bool :
7273 parsed :dbd .dbd_file = dbd .parse_dbd_file (file );
7374 if not len (parsed .definitions ):
7475 print (f"No definitions found in { file } ! Skipping" );
75- continue ;
76+ return False ;
77+
78+ dirname :str = os .path .dirname (file );
79+ name :str = os .path .splitext (os .path .basename (file ))[0 ];
80+ if keys .get (name , None ):
81+ return True ; # Already processed
7682
7783 types :dict [str ,str ] = {};
78- foreigns :dict [str ,str ] = {};
84+ foreigns :dict [str ,list [ str ] ] = {};
7985 column :dbd .column_definition
8086 for column in parsed .columns :
8187 types [column .name ] = column .type ;
8288 if column .foreign :
83- foreigns [column .name ] = f"FOREIGN KEY (` { column .name } `) REFERENCES ` { column . foreign . table } ` (` { column . foreign . column } `) ON DELETE NO ACTION ON UPDATE NO ACTION" ;
89+ foreigns [column .name ] = column .foreign ;
8490
8591 definition :dbd .definitions = None ;
8692 if args .layout :
8793 definition = next (defn for defn in parsed .definitions if args .layout in defn .layouts );
8894 if not definition :
8995 print (f"No definition found for layout { args .layout } ! Skipping" );
90- continue ;
96+ return False ;
9197 elif args .build :
9298 definition = next (defn for defn in parsed .definitions if args .build in defn .builds );
9399
@@ -96,25 +102,41 @@ def get_sql_type(type:str, int_width:int=0, is_unsigned:bool=False)->str:
96102 lambda defn : max (getattr (build , 'build' , getattr (build [- 1 ], 'build' , 0 )) for build in defn .builds )
97103 );
98104
99- name :str = os .path .splitext (os .path .basename (file ))[0 ];
100-
101105 # TODO: include comments in sql
102106 columns :list [str ] = [];
103107 indices :list [str ] = [];
104108 fkeys :list [str ] = [];
105109 entry :dbd .definition_entry
106110 for entry in definition .entries :
107- column = f"`{ entry .column } ` { get_sql_type (types .get (entry .column ), entry .int_width , entry .is_unsigned )} " ;
111+ sql_type :str = get_sql_type (types .get (entry .column ), entry .int_width , entry .is_unsigned );
112+ suffix :str = '' ;
108113 if 'id' in entry .annotation :
109- column += ' PRIMARY KEY' ;
110- elif entry .column in foreigns .keys ():
111- fkeys .append (foreigns .get (entry .column ));
114+ suffix = 'PRIMARY KEY' ;
115+ keys [name ][entry .column ] = sql_type ;
116+ elif (foreign := foreigns .get (entry .column , None )):
117+ # TODO: unhack!
118+ if not keys .get (foreign .table .string , {}).get (foreign .column .string , None ):
119+ foreign_dbd :str = next ((f for f in dbds if os .path .basename (f ) == f"{ foreign .table } .dbd" ), None );
120+ if foreign_dbd :
121+ if not process_dbd (foreign_dbd ):
122+ print (f"Could not process table { foreign .table } referenced by { name } .{ entry .column } " );
123+ return False ;
124+ if not foreign_dbd :
125+ print (f"FK { name } .{ entry .column } references { foreign .column } in { foreign .table } which was not supplied" );
126+
127+ sql_type = keys [foreign .table .string ].get (foreign .column .string , None ) or sql_type ;
128+ fkeys .append (
129+ f"FOREIGN KEY (`{ entry .column } `) "
130+ f"REFERENCES `{ foreign .table } ` (`{ foreign .column } `) "
131+ 'ON DELETE NO ACTION ON UPDATE NO ACTION'
132+ );
112133 elif 'relation' in entry .annotation :
134+ keys [name ][entry .column ] = sql_type ;
113135 indices .append (f"INDEX (`{ entry .column } `)" );
114136 # TODO: Get self-referencing keys to work
115137 #fkeys.append(f"FOREIGN KEY (`{entry.column}`) REFERENCES `{name}` (`{entry.column}`) ON DELETE NO ACTION ON UPDATE NO ACTION");
116138
117- columns .append (column );
139+ columns .append (f"` { entry . column } ` { sql_type } { suffix } " );
118140
119141 fields :list [str ] = [',' .join (columns )];
120142 if len (indices ):
@@ -131,6 +153,11 @@ def get_sql_type(type:str, int_width:int=0, is_unsigned:bool=False)->str:
131153 with open (os .path .join (outdir , f"{ name } .sql" ), 'w' ) as file :
132154 file .write (stmt );
133155
156+ return True ;
157+
158+ for file in dbds :
159+ process_dbd (file );
160+
134161if outfile :
135162 with open (outfile , 'a' ) as file :
136163 file .write ("SET SESSION FOREIGN_KEY_CHECKS=1;\n " );
0 commit comments