diff --git a/generator/templates/builders_create.gotpl b/generator/templates/builders_create.gotpl index 556547f..0cb1874 100644 --- a/generator/templates/builders_create.gotpl +++ b/generator/templates/builders_create.gotpl @@ -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, diff --git a/generator/templates/model_create.gotpl b/generator/templates/model_create.gotpl index 039f703..4535bc2 100644 --- a/generator/templates/model_create.gotpl +++ b/generator/templates/model_create.gotpl @@ -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, + ) } diff --git a/integration/valk/category.go b/integration/valk/category.go index e1771bb..44d5d5e 100644 --- a/integration/valk/category.go +++ b/integration/valk/category.go @@ -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]{ diff --git a/integration/valk/categoryToPost.go b/integration/valk/categoryToPost.go index 516743b..d517141 100644 --- a/integration/valk/categoryToPost.go +++ b/integration/valk/categoryToPost.go @@ -248,102 +248,27 @@ func (d *CategoryToPostDelegate) CreateManyAndReturn(records ...RecordInput) *Cr } func (q *Queries) executeCategoryToPostCreateMany(ctx context.Context, records []RecordInput) (int64, error) { - if len(records) == 0 { - return 0, nil - } - for i, rec := range records { - if err := validateCategoryToPostCreate(rec.Assignments); err != nil { - return 0, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - if q.dialect.SupportsBulkInsert() { - rowMaps := categoryToPostRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "CategoryToPost", rowMaps, CategoryToPostColOrder, 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.executeCategoryToPostCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - count++ - } - return nil - }) - return count, err + return executeCreateMany(ctx, q, records, "CategoryToPost", CategoryToPostColOrder, + validateCategoryToPostCreate, + categoryToPostRecordsToRowMaps, + func(ctx context.Context, assignments []FieldAssignment) (*CategoryToPost, error) { + return q.executeCategoryToPostCreate(ctx, assignments, nil, nil) + }, + ) } func (q *Queries) executeCategoryToPostCreateManyAndReturn(ctx context.Context, records []RecordInput, selects *CategoryToPostSelect, omits *CategoryToPostOmit) ([]*CategoryToPost, error) { - if len(records) == 0 { - return nil, nil - } - for i, rec := range records { - if err := validateCategoryToPostCreate(rec.Assignments); err != nil { - return nil, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - hasRelations := selects.hasAnyRelation() - returningCols := q.selectCategoryToPostCols(selects, omits) - - if q.dialect.SupportsBulkInsert() { - rowMaps := categoryToPostRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "CategoryToPost", rowMaps, CategoryToPostColOrder, returningCols) - recordsOut := make([]*CategoryToPost, 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 CategoryToPost - 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.loadCategoryToPostRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil - } - - recordsOut := make([]*CategoryToPost, 0) - err := q.transaction(ctx, func(txQ *Queries) error { - for _, rec := range records { - res, err := txQ.executeCategoryToPostCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - recordsOut = append(recordsOut, res) - } - - if hasRelations { - return txQ.loadCategoryToPostRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil + return executeCreateManyAndReturn(ctx, q, records, "CategoryToPost", CategoryToPostColOrder, selects, omits, + validateCategoryToPostCreate, + categoryToPostRecordsToRowMaps, + q.selectCategoryToPostCols, + q.loadCategoryToPostRelations, + (*CategoryToPost).ScanFields, + func(ctx context.Context, assignments []FieldAssignment) (*CategoryToPost, error) { + return q.executeCategoryToPostCreate(ctx, assignments, nil, nil) + }, + (*CategoryToPostSelect).hasAnyRelation, + ) } func (d *CategoryToPostDelegate) FindUnique(where UniquePredicate) *FindUniqueBuilder[CategoryToPost, CategoryToPostSelect, CategoryToPostOmit] { return &FindUniqueBuilder[CategoryToPost, CategoryToPostSelect, CategoryToPostOmit]{ diff --git a/integration/valk/client.go b/integration/valk/client.go index 6f2d944..31b10af 100644 --- a/integration/valk/client.go +++ b/integration/valk/client.go @@ -1318,6 +1318,129 @@ func executeInsert[M any]( return &res, nil } +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, diff --git a/integration/valk/comment.go b/integration/valk/comment.go index 74f7308..ef60cd3 100644 --- a/integration/valk/comment.go +++ b/integration/valk/comment.go @@ -405,102 +405,27 @@ func (d *CommentDelegate) CreateManyAndReturn(records ...RecordInput) *CreateMan } func (q *Queries) executeCommentCreateMany(ctx context.Context, records []RecordInput) (int64, error) { - if len(records) == 0 { - return 0, nil - } - for i, rec := range records { - if err := validateCommentCreate(rec.Assignments); err != nil { - return 0, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - if q.dialect.SupportsBulkInsert() { - rowMaps := commentRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "Comment", rowMaps, CommentColOrder, 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.executeCommentCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - count++ - } - return nil - }) - return count, err + return executeCreateMany(ctx, q, records, "Comment", CommentColOrder, + validateCommentCreate, + commentRecordsToRowMaps, + func(ctx context.Context, assignments []FieldAssignment) (*Comment, error) { + return q.executeCommentCreate(ctx, assignments, nil, nil) + }, + ) } func (q *Queries) executeCommentCreateManyAndReturn(ctx context.Context, records []RecordInput, selects *CommentSelect, omits *CommentOmit) ([]*Comment, error) { - if len(records) == 0 { - return nil, nil - } - for i, rec := range records { - if err := validateCommentCreate(rec.Assignments); err != nil { - return nil, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - hasRelations := selects.hasAnyRelation() - returningCols := q.selectCommentCols(selects, omits) - - if q.dialect.SupportsBulkInsert() { - rowMaps := commentRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "Comment", rowMaps, CommentColOrder, returningCols) - recordsOut := make([]*Comment, 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 Comment - 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.loadCommentRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil - } - - recordsOut := make([]*Comment, 0) - err := q.transaction(ctx, func(txQ *Queries) error { - for _, rec := range records { - res, err := txQ.executeCommentCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - recordsOut = append(recordsOut, res) - } - - if hasRelations { - return txQ.loadCommentRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil + return executeCreateManyAndReturn(ctx, q, records, "Comment", CommentColOrder, selects, omits, + validateCommentCreate, + commentRecordsToRowMaps, + q.selectCommentCols, + q.loadCommentRelations, + (*Comment).ScanFields, + func(ctx context.Context, assignments []FieldAssignment) (*Comment, error) { + return q.executeCommentCreate(ctx, assignments, nil, nil) + }, + (*CommentSelect).hasAnyRelation, + ) } func (d *CommentDelegate) FindUnique(where UniquePredicate) *FindUniqueBuilder[Comment, CommentSelect, CommentOmit] { return &FindUniqueBuilder[Comment, CommentSelect, CommentOmit]{ diff --git a/integration/valk/post.go b/integration/valk/post.go index f4df486..99a7d45 100644 --- a/integration/valk/post.go +++ b/integration/valk/post.go @@ -333,102 +333,27 @@ func (d *PostDelegate) CreateManyAndReturn(records ...RecordInput) *CreateManyAn } func (q *Queries) executePostCreateMany(ctx context.Context, records []RecordInput) (int64, error) { - if len(records) == 0 { - return 0, nil - } - for i, rec := range records { - if err := validatePostCreate(rec.Assignments); err != nil { - return 0, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - if q.dialect.SupportsBulkInsert() { - rowMaps := postRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "Post", rowMaps, PostColOrder, 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.executePostCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - count++ - } - return nil - }) - return count, err + return executeCreateMany(ctx, q, records, "Post", PostColOrder, + validatePostCreate, + postRecordsToRowMaps, + func(ctx context.Context, assignments []FieldAssignment) (*Post, error) { + return q.executePostCreate(ctx, assignments, nil, nil) + }, + ) } func (q *Queries) executePostCreateManyAndReturn(ctx context.Context, records []RecordInput, selects *PostSelect, omits *PostOmit) ([]*Post, error) { - if len(records) == 0 { - return nil, nil - } - for i, rec := range records { - if err := validatePostCreate(rec.Assignments); err != nil { - return nil, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - hasRelations := selects.hasAnyRelation() - returningCols := q.selectPostCols(selects, omits) - - if q.dialect.SupportsBulkInsert() { - rowMaps := postRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "Post", rowMaps, PostColOrder, returningCols) - recordsOut := make([]*Post, 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 Post - 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.loadPostRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil - } - - recordsOut := make([]*Post, 0) - err := q.transaction(ctx, func(txQ *Queries) error { - for _, rec := range records { - res, err := txQ.executePostCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - recordsOut = append(recordsOut, res) - } - - if hasRelations { - return txQ.loadPostRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil + return executeCreateManyAndReturn(ctx, q, records, "Post", PostColOrder, selects, omits, + validatePostCreate, + postRecordsToRowMaps, + q.selectPostCols, + q.loadPostRelations, + (*Post).ScanFields, + func(ctx context.Context, assignments []FieldAssignment) (*Post, error) { + return q.executePostCreate(ctx, assignments, nil, nil) + }, + (*PostSelect).hasAnyRelation, + ) } func (d *PostDelegate) FindUnique(where UniquePredicate) *FindUniqueBuilder[Post, PostSelect, PostOmit] { return &FindUniqueBuilder[Post, PostSelect, PostOmit]{ diff --git a/integration/valk/profile.go b/integration/valk/profile.go index 14a9011..e276134 100644 --- a/integration/valk/profile.go +++ b/integration/valk/profile.go @@ -279,102 +279,27 @@ func (d *ProfileDelegate) CreateManyAndReturn(records ...RecordInput) *CreateMan } func (q *Queries) executeProfileCreateMany(ctx context.Context, records []RecordInput) (int64, error) { - if len(records) == 0 { - return 0, nil - } - for i, rec := range records { - if err := validateProfileCreate(rec.Assignments); err != nil { - return 0, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - if q.dialect.SupportsBulkInsert() { - rowMaps := profileRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "Profile", rowMaps, ProfileColOrder, 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.executeProfileCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - count++ - } - return nil - }) - return count, err + return executeCreateMany(ctx, q, records, "Profile", ProfileColOrder, + validateProfileCreate, + profileRecordsToRowMaps, + func(ctx context.Context, assignments []FieldAssignment) (*Profile, error) { + return q.executeProfileCreate(ctx, assignments, nil, nil) + }, + ) } func (q *Queries) executeProfileCreateManyAndReturn(ctx context.Context, records []RecordInput, selects *ProfileSelect, omits *ProfileOmit) ([]*Profile, error) { - if len(records) == 0 { - return nil, nil - } - for i, rec := range records { - if err := validateProfileCreate(rec.Assignments); err != nil { - return nil, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - hasRelations := selects.hasAnyRelation() - returningCols := q.selectProfileCols(selects, omits) - - if q.dialect.SupportsBulkInsert() { - rowMaps := profileRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "Profile", rowMaps, ProfileColOrder, returningCols) - recordsOut := make([]*Profile, 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 Profile - 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.loadProfileRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil - } - - recordsOut := make([]*Profile, 0) - err := q.transaction(ctx, func(txQ *Queries) error { - for _, rec := range records { - res, err := txQ.executeProfileCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - recordsOut = append(recordsOut, res) - } - - if hasRelations { - return txQ.loadProfileRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil + return executeCreateManyAndReturn(ctx, q, records, "Profile", ProfileColOrder, selects, omits, + validateProfileCreate, + profileRecordsToRowMaps, + q.selectProfileCols, + q.loadProfileRelations, + (*Profile).ScanFields, + func(ctx context.Context, assignments []FieldAssignment) (*Profile, error) { + return q.executeProfileCreate(ctx, assignments, nil, nil) + }, + (*ProfileSelect).hasAnyRelation, + ) } func (d *ProfileDelegate) FindUnique(where UniquePredicate) *FindUniqueBuilder[Profile, ProfileSelect, ProfileOmit] { return &FindUniqueBuilder[Profile, ProfileSelect, ProfileOmit]{ diff --git a/integration/valk/user.go b/integration/valk/user.go index 4aad02e..b81b81b 100644 --- a/integration/valk/user.go +++ b/integration/valk/user.go @@ -381,102 +381,27 @@ func (d *UserDelegate) CreateManyAndReturn(records ...RecordInput) *CreateManyAn } func (q *Queries) executeUserCreateMany(ctx context.Context, records []RecordInput) (int64, error) { - if len(records) == 0 { - return 0, nil - } - for i, rec := range records { - if err := validateUserCreate(rec.Assignments); err != nil { - return 0, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - if q.dialect.SupportsBulkInsert() { - rowMaps := userRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "User", rowMaps, UserColOrder, 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.executeUserCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - count++ - } - return nil - }) - return count, err + return executeCreateMany(ctx, q, records, "User", UserColOrder, + validateUserCreate, + userRecordsToRowMaps, + func(ctx context.Context, assignments []FieldAssignment) (*User, error) { + return q.executeUserCreate(ctx, assignments, nil, nil) + }, + ) } func (q *Queries) executeUserCreateManyAndReturn(ctx context.Context, records []RecordInput, selects *UserSelect, omits *UserOmit) ([]*User, error) { - if len(records) == 0 { - return nil, nil - } - for i, rec := range records { - if err := validateUserCreate(rec.Assignments); err != nil { - return nil, fmt.Errorf("validation failed at index %d: %w", i, err) - } - } - - hasRelations := selects.hasAnyRelation() - returningCols := q.selectUserCols(selects, omits) - - if q.dialect.SupportsBulkInsert() { - rowMaps := userRecordsToRowMaps(records) - query, vals := buildBulkInsertSQL(q.dialect, "User", rowMaps, UserColOrder, returningCols) - recordsOut := make([]*User, 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 User - 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.loadUserRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil - } - - recordsOut := make([]*User, 0) - err := q.transaction(ctx, func(txQ *Queries) error { - for _, rec := range records { - res, err := txQ.executeUserCreate(ctx, rec.Assignments, nil, nil) - if err != nil { - return err - } - recordsOut = append(recordsOut, res) - } - - if hasRelations { - return txQ.loadUserRelations(ctx, recordsOut, selects) - } - return nil - }) - if err != nil { - return nil, err - } - return recordsOut, nil + return executeCreateManyAndReturn(ctx, q, records, "User", UserColOrder, selects, omits, + validateUserCreate, + userRecordsToRowMaps, + q.selectUserCols, + q.loadUserRelations, + (*User).ScanFields, + func(ctx context.Context, assignments []FieldAssignment) (*User, error) { + return q.executeUserCreate(ctx, assignments, nil, nil) + }, + (*UserSelect).hasAnyRelation, + ) } func (d *UserDelegate) FindUnique(where UniquePredicate) *FindUniqueBuilder[User, UserSelect, UserOmit] { return &FindUniqueBuilder[User, UserSelect, UserOmit]{