@@ -702,12 +702,23 @@ func pydanticNode(name string) *pyast.ClassDef {
702
702
}
703
703
}
704
704
705
- func fieldNode (f Field ) * pyast.Node {
705
+ func fieldNode (f Field , defaultNone bool ) * pyast.Node {
706
+ // TODO: Current AST is showing limitation as annotated assign does not support a value :'(, manually edited :'(
707
+ var value * pyast.Node = nil
708
+ if defaultNone && f .Type .IsNull {
709
+ value = & pyast.Node {
710
+ Node : & pyast.Node_Name {
711
+ Name : & pyast.Name {Id : "None" },
712
+ },
713
+ }
714
+ }
715
+
706
716
return & pyast.Node {
707
717
Node : & pyast.Node_AnnAssign {
708
718
AnnAssign : & pyast.AnnAssign {
709
719
Target : & pyast.Name {Id : f .Name },
710
720
Annotation : f .Type .Annotation (),
721
+ Value : value ,
711
722
Comment : f .Comment ,
712
723
},
713
724
},
@@ -825,7 +836,7 @@ func buildModelsTree(ctx *pyTmplCtx, i *importer) *pyast.Node {
825
836
})
826
837
}
827
838
for _ , f := range m .Fields {
828
- def .Body = append (def .Body , fieldNode (f ))
839
+ def .Body = append (def .Body , fieldNode (f , false ))
829
840
}
830
841
mod .Body = append (mod .Body , & pyast.Node {
831
842
Node : & pyast.Node_ClassDef {
@@ -904,6 +915,8 @@ func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node {
904
915
}
905
916
queryText := fmt .Sprintf ("-- name: %s \\ \\ %s\n %s\n " , q .MethodName , q .Cmd , q .SQL )
906
917
mod .Body = append (mod .Body , assignNode (q .ConstantName , poet .Constant (queryText )))
918
+
919
+ // Generate params structures
907
920
for _ , arg := range q .Args {
908
921
if arg .EmitStruct () {
909
922
var def * pyast.ClassDef
@@ -912,8 +925,18 @@ func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node {
912
925
} else {
913
926
def = dataclassNode (arg .Struct .Name )
914
927
}
915
- for _ , f := range arg .Struct .Fields {
916
- def .Body = append (def .Body , fieldNode (f ))
928
+
929
+ // We need a copy as we want to make sure that nullable params are at the end of the dataclass
930
+ fields := make ([]Field , len (arg .Struct .Fields ))
931
+ copy (fields , arg .Struct .Fields )
932
+
933
+ // Place all nullable fields at the end and try to keep the original order as much as possible
934
+ sort .SliceStable (fields , func (i int , j int ) bool {
935
+ return (fields [j ].Type .IsNull && fields [i ].Type .IsNull != fields [j ].Type .IsNull ) || i < j
936
+ })
937
+
938
+ for _ , f := range fields {
939
+ def .Body = append (def .Body , fieldNode (f , true ))
917
940
}
918
941
mod .Body = append (mod .Body , poet .Node (def ))
919
942
}
@@ -926,7 +949,7 @@ func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node {
926
949
def = dataclassNode (q .Ret .Struct .Name )
927
950
}
928
951
for _ , f := range q .Ret .Struct .Fields {
929
- def .Body = append (def .Body , fieldNode (f ))
952
+ def .Body = append (def .Body , fieldNode (f , false ))
930
953
}
931
954
mod .Body = append (mod .Body , poet .Node (def ))
932
955
}
0 commit comments