Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 0 additions & 63 deletions generator/generator_test.go

This file was deleted.

39 changes: 12 additions & 27 deletions generator/templates/builders_create.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -178,27 +178,18 @@ func executeInsert[M any](
}


func executeCreateMany[M any](
func executeCreateMany(
ctx context.Context,
q *Queries,
records []RecordInput,
rowMaps []map[string]any,
tableName string,
colOrder []string,
validateFn func([]FieldAssignment) error,
rowMapFn func([]RecordInput) []map[string]any,
singleCreateFn func(context.Context, []FieldAssignment) (*M, error),
) (int64, error) {
if len(records) == 0 {
if len(rowMaps) == 0 {
return 0, nil
}
for i, rec := range records {
if err := validateFn(rec.Assignments); err != nil {
return 0, fmt.Errorf("validation failed at index %d: %w", i, err)
}
}

if q.dialect.SupportsBulkInsert() {
rowMaps := rowMapFn(records)
query, vals := buildBulkInsertSQL(q.dialect, tableName, rowMaps, colOrder, nil)
res, err := q.exec(ctx, query, vals...)
if err != nil {
Expand All @@ -209,8 +200,9 @@ func executeCreateMany[M any](

var count int64
err := q.transaction(ctx, func(txQ *Queries) error {
for _, rec := range records {
_, err := singleCreateFn(ctx, rec.Assignments)
for _, rowMap := range rowMaps {
query, vals := buildBulkInsertSQL(txQ.dialect, tableName, []map[string]any{rowMap}, colOrder, nil)
_, err := txQ.exec(ctx, query, vals...)
if err != nil {
return err
}
Expand All @@ -224,33 +216,25 @@ func executeCreateMany[M any](
func executeCreateManyAndReturn[M any, S any, O any](
ctx context.Context,
q *Queries,
records []RecordInput,
rowMaps []map[string]any,
tableName string,
colOrder []string,
selects *S,
omits *O,
validateFn func([]FieldAssignment) error,
rowMapFn func([]RecordInput) []map[string]any,
selectColsFn func(*S, *O, ...string) []string,
loadRelationsFn func(context.Context, []*M, *S) error,
scanFunc func(*M, []string) []any,
singleCreateFn func(context.Context, []FieldAssignment) (*M, error),
hasRelationsFn func(*S) bool,
idCol string,
) ([]*M, error) {
if len(records) == 0 {
if len(rowMaps) == 0 {
return nil, nil
}
for i, rec := range records {
if err := validateFn(rec.Assignments); err != nil {
return nil, fmt.Errorf("validation failed at index %d: %w", i, err)
}
}

hasRelations := selects != nil && hasRelationsFn(selects)
returningCols := selectColsFn(selects, omits)

if q.dialect.SupportsBulkInsert() {
rowMaps := rowMapFn(records)
query, vals := buildBulkInsertSQL(q.dialect, tableName, rowMaps, colOrder, returningCols)
recordsOut := make([]*M, 0)
err := q.transaction(ctx, func(txQ *Queries) error {
Expand Down Expand Up @@ -282,8 +266,9 @@ func executeCreateManyAndReturn[M any, S any, O any](

recordsOut := make([]*M, 0)
err := q.transaction(ctx, func(txQ *Queries) error {
for _, rec := range records {
res, err := singleCreateFn(ctx, rec.Assignments)
for _, rowMap := range rowMaps {
cols, vals := mapToColsVals(rowMap, colOrder)
res, err := executeInsert(ctx, txQ, tableName, cols, vals, returningCols, idCol, scanFunc)
if err != nil {
return err
}
Expand Down
142 changes: 99 additions & 43 deletions generator/templates/model_create.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,64 @@ func assignmentsTo{{ .Model.Name }}Create(assignments []FieldAssignment) {{ .Mod
return input
}

func (s *{{ .Model.Name }}Create) ToRowMap() map[string]any {
m := make(map[string]any, {{ len .Model.ScalarFields }})
{{- range $field := .Model.ScalarFields }}
{{- $col := $field.EffectiveColName }}
{{- $fieldName := capitalize $field.Name }}
{{- if $field.EnumRef }}
{{- if $field.IsArray }}
if s.{{ $fieldName }} != nil {
m["{{ $col }}"] = s.{{ $fieldName }}
}
{{- else }}
if s.{{ $fieldName }} != nil {
m["{{ $col }}"] = *s.{{ $fieldName }}
}
{{- end }}
{{- else if $field.IsArray }}
if s.{{ $fieldName }} != nil {
m["{{ $col }}"] = s.{{ $fieldName }}
}
{{- else }}
{{- if and $field.Default (eq $field.Default.Kind.String "Func") }}
{{- if eq $field.Default.FuncName "autoincrement" }}
if s.{{ $fieldName }} != nil {
m["{{ $col }}"] = *s.{{ $fieldName }}
}
{{- else }}
if s.{{ $fieldName }} != nil {
m["{{ $col }}"] = *s.{{ $fieldName }}
} else {
{{- if eq $field.Default.FuncName "cuid" }}
m["{{ $col }}"] = generateCUID()
{{- else if eq $field.Default.FuncName "uuid" }}
m["{{ $col }}"] = generateUUID()
{{- else if eq $field.Default.FuncName "now" }}
m["{{ $col }}"] = time.Now()
{{- end }}
}
{{- end }}
{{- else if or $field.Optional (ne $field.Default nil) }}
if s.{{ $fieldName }} != nil {
m["{{ $col }}"] = *s.{{ $fieldName }}
}
{{- else }}
{{- if and $field.IsID (eq $field.GoType "string") }}
if s.{{ $fieldName }} != "" {
m["{{ $col }}"] = s.{{ $fieldName }}
} else {
m["{{ $col }}"] = generateCUID()
}
{{- else }}
m["{{ $col }}"] = s.{{ $fieldName }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
return m
}

func (q *Queries) execute{{ .Model.Name }}Create(ctx context.Context, assignments []FieldAssignment, selects *{{ .Model.Name }}Select, omits *{{ .Model.Name }}Omit) (*{{ .Model.Name }}, error) {
input := assignmentsTo{{ .Model.Name }}Create(assignments)

Expand Down Expand Up @@ -266,36 +324,6 @@ func (q *Queries) execute{{ .Model.Name }}Create(ctx context.Context, assignment
return res, nil
}

func {{ lowercase .Model.Name }}RecordsToRowMaps(records []RecordInput) []map[string]any {
rowMaps := make([]map[string]any, len(records))
for i, rec := range records {
m := make(map[string]any, len(rec.Assignments))
for _, a := range rec.Assignments {
m[a.Col] = a.Val
}
{{- range $field := .Model.ScalarFields }}
{{- $col := $field.EffectiveColName }}
{{- if and $field.Default (eq $field.Default.Kind.String "Func") }}
if _, ok := m["{{ $col }}"]; !ok {
{{- if eq $field.Default.FuncName "cuid" }}
m["{{ $col }}"] = generateCUID()
{{- else if eq $field.Default.FuncName "uuid" }}
m["{{ $col }}"] = generateUUID()
{{- else if eq $field.Default.FuncName "now" }}
m["{{ $col }}"] = time.Now()
{{- end }}
}
{{- else if and $field.IsID (eq $field.GoType "string") }}
if _, ok := m["{{ $col }}"]; !ok {
m["{{ $col }}"] = generateCUID()
}
{{- end }}
{{- end }}
rowMaps[i] = m
}
return rowMaps
}

func (d *{{ .Model.Name }}Delegate) CreateMany(records ...RecordInput) *CreateManyBuilder[{{ .Model.Name }}] {
return &CreateManyBuilder[{{ .Model.Name }}]{
client: d.client,
Expand All @@ -313,25 +341,53 @@ func (d *{{ .Model.Name }}Delegate) CreateManyAndReturn(records ...RecordInput)
}

func (q *Queries) execute{{ .Model.Name }}CreateMany(ctx context.Context, records []RecordInput) (int64, error) {
return executeCreateMany(ctx, q, records, "{{ .Model.EffectiveTableName }}", {{ .Model.Name }}ColOrder,
validate{{ .Model.Name }}Create,
{{ lowercase .Model.Name }}RecordsToRowMaps,
func(ctx context.Context, assignments []FieldAssignment) (*{{ .Model.Name }}, error) {
return q.execute{{ .Model.Name }}Create(ctx, assignments, nil, nil)
},
)
rowMaps := make([]map[string]any, len(records))
for i, rec := range records {
if err := validate{{ .Model.Name }}Create(rec.Assignments); err != nil {
return 0, fmt.Errorf("validation failed at index %d: %w", i, err)
}
input := assignmentsTo{{ .Model.Name }}Create(rec.Assignments)
if q.{{ .Model.Name }}.beforeCreate != nil {
if err := q.{{ .Model.Name }}.beforeCreate(ctx, &input); err != nil {
return 0, err
}
}
rowMaps[i] = input.ToRowMap()
}
return executeCreateMany(ctx, q, rowMaps, "{{ .Model.EffectiveTableName }}", {{ .Model.Name }}ColOrder)
}

func (q *Queries) execute{{ .Model.Name }}CreateManyAndReturn(ctx context.Context, records []RecordInput, selects *{{ .Model.Name }}Select, omits *{{ .Model.Name }}Omit) ([]*{{ .Model.Name }}, error) {
return executeCreateManyAndReturn(ctx, q, records, "{{ .Model.EffectiveTableName }}", {{ .Model.Name }}ColOrder, selects, omits,
validate{{ .Model.Name }}Create,
{{ lowercase .Model.Name }}RecordsToRowMaps,
rowMaps := make([]map[string]any, len(records))
idCol := "{{ range $field := .Model.ScalarFields }}{{ if $field.IsID }}{{ $field.EffectiveColName }}{{ end }}{{ end }}"
for i, rec := range records {
if err := validate{{ .Model.Name }}Create(rec.Assignments); err != nil {
return nil, fmt.Errorf("validation failed at index %d: %w", i, err)
}
input := assignmentsTo{{ .Model.Name }}Create(rec.Assignments)
if q.{{ .Model.Name }}.beforeCreate != nil {
if err := q.{{ .Model.Name }}.beforeCreate(ctx, &input); err != nil {
return nil, err
}
}
rowMaps[i] = input.ToRowMap()
}
results, err := executeCreateManyAndReturn(ctx, q, rowMaps, "{{ .Model.EffectiveTableName }}", {{ .Model.Name }}ColOrder, selects, omits,
q.select{{ .Model.Name }}Cols,
q.load{{ .Model.Name }}Relations,
(*{{ .Model.Name }}).ScanFields,
func(ctx context.Context, assignments []FieldAssignment) (*{{ .Model.Name }}, error) {
return q.execute{{ .Model.Name }}Create(ctx, assignments, nil, nil)
},
(*{{ .Model.Name }}Select).hasAnyRelation,
idCol,
)
if err != nil {
return nil, err
}
if q.{{ .Model.Name }}.afterCreate != nil {
for _, r := range results {
if err := q.{{ .Model.Name }}.afterCreate(ctx, r); err != nil {
return nil, err
}
}
}
return results, nil
}
Loading
Loading