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
123 changes: 123 additions & 0 deletions generator/templates/builders_create.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,129 @@ func executeInsert[M any](
}


func executeCreateMany[M any](
ctx context.Context,
q *Queries,
records []RecordInput,
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 {
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 {
return 0, err
}
return res.RowsAffected()
}

var count int64
err := q.transaction(ctx, func(txQ *Queries) error {
for _, rec := range records {
_, err := singleCreateFn(ctx, rec.Assignments)
if err != nil {
return err
}
count++
}
return nil
})
return count, err
}

func executeCreateManyAndReturn[M any, S any, O any](
ctx context.Context,
q *Queries,
records []RecordInput,
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,
) ([]*M, error) {
if len(records) == 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 {
rows, err := txQ.query(ctx, query, vals...)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var record M
if err := rows.Scan(scanFunc(&record, returningCols)...); err != nil {
return err
}
recordsOut = append(recordsOut, &record)
}
if err := rows.Err(); err != nil {
return err
}
if hasRelations {
return loadRelationsFn(ctx, recordsOut, selects)
}
return nil
})
if err != nil {
return nil, err
}
return recordsOut, nil
}

recordsOut := make([]*M, 0)
err := q.transaction(ctx, func(txQ *Queries) error {
for _, rec := range records {
res, err := singleCreateFn(ctx, rec.Assignments)
if err != nil {
return err
}
recordsOut = append(recordsOut, res)
}

if hasRelations {
return loadRelationsFn(ctx, recordsOut, selects)
}
return nil
})
if err != nil {
return nil, err
}
return recordsOut, nil
}

func loadRelation[P any, C any](
ctx context.Context,
q *Queries,
Expand Down
111 changes: 18 additions & 93 deletions generator/templates/model_create.gotpl
Original file line number Diff line number Diff line change
Expand Up @@ -313,100 +313,25 @@ func (d *{{ .Model.Name }}Delegate) CreateManyAndReturn(records ...RecordInput)
}

func (q *Queries) execute{{ .Model.Name }}CreateMany(ctx context.Context, records []RecordInput) (int64, error) {
if len(records) == 0 {
return 0, nil
}
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)
}
}

if q.dialect.SupportsBulkInsert() {
rowMaps := {{ lowercase .Model.Name }}RecordsToRowMaps(records)
query, vals := buildBulkInsertSQL(q.dialect, "{{ .Model.EffectiveTableName }}", rowMaps, {{ .Model.Name }}ColOrder, nil)
res, err := q.exec(ctx, query, vals...)
if err != nil {
return 0, err
}
return res.RowsAffected()
}

var count int64
err := q.transaction(ctx, func(txQ *Queries) error {
for _, rec := range records {
_, err := txQ.execute{{ .Model.Name }}Create(ctx, rec.Assignments, nil, nil)
if err != nil {
return err
}
count++
}
return nil
})
return count, err
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)
},
)
}

func (q *Queries) execute{{ .Model.Name }}CreateManyAndReturn(ctx context.Context, records []RecordInput, selects *{{ .Model.Name }}Select, omits *{{ .Model.Name }}Omit) ([]*{{ .Model.Name }}, error) {
if len(records) == 0 {
return nil, nil
}
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)
}
}

hasRelations := selects.hasAnyRelation()
returningCols := q.select{{ .Model.Name }}Cols(selects, omits)

if q.dialect.SupportsBulkInsert() {
rowMaps := {{ lowercase .Model.Name }}RecordsToRowMaps(records)
query, vals := buildBulkInsertSQL(q.dialect, "{{ .Model.EffectiveTableName }}", rowMaps, {{ .Model.Name }}ColOrder, returningCols)
recordsOut := make([]*{{ .Model.Name }}, 0)
err := q.transaction(ctx, func(txQ *Queries) error {
rows, err := txQ.query(ctx, query, vals...)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var record {{ .Model.Name }}
if err := rows.Scan(record.ScanFields(returningCols)...); err != nil {
return err
}
recordsOut = append(recordsOut, &record)
}
if err := rows.Err(); err != nil {
return err
}
if hasRelations {
return txQ.load{{ .Model.Name }}Relations(ctx, recordsOut, selects)
}
return nil
})
if err != nil {
return nil, err
}
return recordsOut, nil
}

recordsOut := make([]*{{ .Model.Name }}, 0)
err := q.transaction(ctx, func(txQ *Queries) error {
for _, rec := range records {
res, err := txQ.execute{{ .Model.Name }}Create(ctx, rec.Assignments, nil, nil)
if err != nil {
return err
}
recordsOut = append(recordsOut, res)
}

if hasRelations {
return txQ.load{{ .Model.Name }}Relations(ctx, recordsOut, selects)
}
return nil
})
if err != nil {
return nil, err
}
return recordsOut, nil
return executeCreateManyAndReturn(ctx, q, records, "{{ .Model.EffectiveTableName }}", {{ .Model.Name }}ColOrder, selects, omits,
validate{{ .Model.Name }}Create,
{{ lowercase .Model.Name }}RecordsToRowMaps,
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,
)
}
111 changes: 18 additions & 93 deletions integration/valk/category.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,102 +249,27 @@ func (d *CategoryDelegate) CreateManyAndReturn(records ...RecordInput) *CreateMa
}

func (q *Queries) executeCategoryCreateMany(ctx context.Context, records []RecordInput) (int64, error) {
if len(records) == 0 {
return 0, nil
}
for i, rec := range records {
if err := validateCategoryCreate(rec.Assignments); err != nil {
return 0, fmt.Errorf("validation failed at index %d: %w", i, err)
}
}

if q.dialect.SupportsBulkInsert() {
rowMaps := categoryRecordsToRowMaps(records)
query, vals := buildBulkInsertSQL(q.dialect, "Category", rowMaps, CategoryColOrder, nil)
res, err := q.exec(ctx, query, vals...)
if err != nil {
return 0, err
}
return res.RowsAffected()
}

var count int64
err := q.transaction(ctx, func(txQ *Queries) error {
for _, rec := range records {
_, err := txQ.executeCategoryCreate(ctx, rec.Assignments, nil, nil)
if err != nil {
return err
}
count++
}
return nil
})
return count, err
return executeCreateMany(ctx, q, records, "Category", CategoryColOrder,
validateCategoryCreate,
categoryRecordsToRowMaps,
func(ctx context.Context, assignments []FieldAssignment) (*Category, error) {
return q.executeCategoryCreate(ctx, assignments, nil, nil)
},
)
}

func (q *Queries) executeCategoryCreateManyAndReturn(ctx context.Context, records []RecordInput, selects *CategorySelect, omits *CategoryOmit) ([]*Category, error) {
if len(records) == 0 {
return nil, nil
}
for i, rec := range records {
if err := validateCategoryCreate(rec.Assignments); err != nil {
return nil, fmt.Errorf("validation failed at index %d: %w", i, err)
}
}

hasRelations := selects.hasAnyRelation()
returningCols := q.selectCategoryCols(selects, omits)

if q.dialect.SupportsBulkInsert() {
rowMaps := categoryRecordsToRowMaps(records)
query, vals := buildBulkInsertSQL(q.dialect, "Category", rowMaps, CategoryColOrder, returningCols)
recordsOut := make([]*Category, 0)
err := q.transaction(ctx, func(txQ *Queries) error {
rows, err := txQ.query(ctx, query, vals...)
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var record Category
if err := rows.Scan(record.ScanFields(returningCols)...); err != nil {
return err
}
recordsOut = append(recordsOut, &record)
}
if err := rows.Err(); err != nil {
return err
}
if hasRelations {
return txQ.loadCategoryRelations(ctx, recordsOut, selects)
}
return nil
})
if err != nil {
return nil, err
}
return recordsOut, nil
}

recordsOut := make([]*Category, 0)
err := q.transaction(ctx, func(txQ *Queries) error {
for _, rec := range records {
res, err := txQ.executeCategoryCreate(ctx, rec.Assignments, nil, nil)
if err != nil {
return err
}
recordsOut = append(recordsOut, res)
}

if hasRelations {
return txQ.loadCategoryRelations(ctx, recordsOut, selects)
}
return nil
})
if err != nil {
return nil, err
}
return recordsOut, nil
return executeCreateManyAndReturn(ctx, q, records, "Category", CategoryColOrder, selects, omits,
validateCategoryCreate,
categoryRecordsToRowMaps,
q.selectCategoryCols,
q.loadCategoryRelations,
(*Category).ScanFields,
func(ctx context.Context, assignments []FieldAssignment) (*Category, error) {
return q.executeCategoryCreate(ctx, assignments, nil, nil)
},
(*CategorySelect).hasAnyRelation,
)
}
func (d *CategoryDelegate) FindUnique(where UniquePredicate) *FindUniqueBuilder[Category, CategorySelect, CategoryOmit] {
return &FindUniqueBuilder[Category, CategorySelect, CategoryOmit]{
Expand Down
Loading
Loading