1313 as columns
1414The type hierarchy will be translated to corresponding `union` declarations.
1515"""
16+ import typing
1617
1718import inflection
1819
2324log = logging .getLogger (__name__ )
2425
2526
26- def dbtype (typename ):
27- """ translate a type to a dbscheme counterpart, using `@lower_underscore` format for classes """
27+ def dbtype (typename : str , add_or_none_except : typing .Optional [str ] = None ) -> str :
28+ """ translate a type to a dbscheme counterpart, using `@lower_underscore` format for classes.
29+ For class types, appends an underscore followed by `null` if provided
30+ """
2831 if typename [0 ].isupper ():
29- return "@" + inflection .underscore (typename )
32+ underscored = inflection .underscore (typename )
33+ if add_or_none_except is not None and typename != add_or_none_except :
34+ suffix = "_or_none"
35+ else :
36+ suffix = ""
37+ return f"@{ underscored } { suffix } "
3038 return typename
3139
3240
33- def cls_to_dbscheme (cls : schema .Class ):
41+ def cls_to_dbscheme (cls : schema .Class , add_or_none_except : typing . Optional [ str ] = None ):
3442 """ Yield all dbscheme entities needed to model class `cls` """
3543 if cls .derived :
3644 yield Union (dbtype (cls .name ), (dbtype (c ) for c in cls .derived ))
@@ -48,7 +56,7 @@ def cls_to_dbscheme(cls: schema.Class):
4856 columns = [
4957 Column ("id" , type = dbtype (cls .name ), binding = binding ),
5058 ] + [
51- Column (f .name , dbtype (f .type )) for f in cls .properties if f .is_single
59+ Column (f .name , dbtype (f .type , add_or_none_except )) for f in cls .properties if f .is_single
5260 ],
5361 dir = dir ,
5462 )
@@ -61,7 +69,7 @@ def cls_to_dbscheme(cls: schema.Class):
6169 columns = [
6270 Column ("id" , type = dbtype (cls .name )),
6371 Column ("index" , type = "int" ),
64- Column (inflection .singularize (f .name ), dbtype (f .type )),
72+ Column (inflection .singularize (f .name ), dbtype (f .type , add_or_none_except )),
6573 ],
6674 dir = dir ,
6775 )
@@ -71,7 +79,7 @@ def cls_to_dbscheme(cls: schema.Class):
7179 name = inflection .tableize (f"{ cls .name } _{ f .name } " ),
7280 columns = [
7381 Column ("id" , type = dbtype (cls .name )),
74- Column (f .name , dbtype (f .type )),
82+ Column (f .name , dbtype (f .type , add_or_none_except )),
7583 ],
7684 dir = dir ,
7785 )
@@ -87,7 +95,17 @@ def cls_to_dbscheme(cls: schema.Class):
8795
8896
8997def get_declarations (data : schema .Schema ):
90- return [d for cls in data .classes .values () for d in cls_to_dbscheme (cls )]
98+ add_or_none_except = data .root_class .name if data .null else None
99+ declarations = [d for cls in data .classes .values () for d in cls_to_dbscheme (cls , add_or_none_except )]
100+ if data .null :
101+ property_classes = {
102+ prop .type for cls in data .classes .values () for prop in cls .properties
103+ if cls .name != data .null and prop .type and prop .type [0 ].isupper ()
104+ }
105+ declarations += [
106+ Union (dbtype (t , data .null ), [dbtype (t ), dbtype (data .null )]) for t in sorted (property_classes )
107+ ]
108+ return declarations
91109
92110
93111def get_includes (data : schema .Schema , include_dir : pathlib .Path , swift_dir : pathlib .Path ):
0 commit comments