@@ -702,12 +702,23 @@ func pydanticNode(name string) *pyast.ClassDef {
702702}
703703}
704704
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+
706716return & pyast.Node {
707717Node :& pyast.Node_AnnAssign {
708718AnnAssign :& pyast.AnnAssign {
709719Target :& pyast.Name {Id :f .Name },
710720Annotation :f .Type .Annotation (),
721+ Value :value ,
711722Comment :f .Comment ,
712723},
713724},
@@ -825,7 +836,7 @@ func buildModelsTree(ctx *pyTmplCtx, i *importer) *pyast.Node {
825836})
826837}
827838for _ ,f := range m .Fields {
828- def .Body = append (def .Body ,fieldNode (f ))
839+ def .Body = append (def .Body ,fieldNode (f , false ))
829840}
830841mod .Body = append (mod .Body ,& pyast.Node {
831842Node :& pyast.Node_ClassDef {
@@ -904,6 +915,8 @@ func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node {
904915}
905916queryText := fmt .Sprintf ("-- name: %s\\ \\ %s\n %s\n " ,q .MethodName ,q .Cmd ,q .SQL )
906917mod .Body = append (mod .Body ,assignNode (q .ConstantName ,poet .Constant (queryText )))
918+
919+ // Generate params structures
907920for _ ,arg := range q .Args {
908921if arg .EmitStruct () {
909922var def * pyast.ClassDef
@@ -912,8 +925,18 @@ func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node {
912925}else {
913926def = dataclassNode (arg .Struct .Name )
914927}
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 ))
917940}
918941mod .Body = append (mod .Body ,poet .Node (def ))
919942}
@@ -926,7 +949,7 @@ func buildQueryTree(ctx *pyTmplCtx, i *importer, source string) *pyast.Node {
926949def = dataclassNode (q .Ret .Struct .Name )
927950}
928951for _ ,f := range q .Ret .Struct .Fields {
929- def .Body = append (def .Body ,fieldNode (f ))
952+ def .Body = append (def .Body ,fieldNode (f , false ))
930953}
931954mod .Body = append (mod .Body ,poet .Node (def ))
932955}