[server][core] use copyfrom to bulk-insert rows

This commit is contained in:
Abhishek Shroff
2024-10-19 13:07:31 +05:30
parent 056b966e5e
commit 774a64f779
5 changed files with 101 additions and 36 deletions

View File

@@ -486,7 +486,42 @@ func (f filesystem) Copy(src Resource, target string, id uuid.UUID, recursive, o
return
}
var tree []db.ReadDirRow
if recursive && src.Dir {
var err error
tree, err = f.db.ReadDir(f.ctx, db.ReadDirParams{ID: src.ID, IncludeRoot: false, Recursive: true})
if err != nil {
return Resource{}, err
}
}
create := make([]db.CreateResourcesParams, 0, len(tree))
copy := make(map[uuid.UUID]uuid.UUID)
ids := make(map[string]uuid.UUID)
if src.Dir {
ids[""] = id
} else {
copy[src.ID] = id
}
for _, src := range tree {
id := uuid.New()
parent := ids[src.Path[0:strings.LastIndex(src.Path, "/")]]
create = append(create, db.CreateResourcesParams{
ID: id,
Parent: parent,
Name: src.Name,
Dir: src.Dir,
ContentType: src.ContentType,
ContentSha256: src.ContentSha256,
})
if src.Dir {
ids[src.Path] = id
} else {
copy[src.ID] = id
}
}
e = f.db.WithTx(f.ctx, func(dbh *db.DbHandler) error {
f := f.withDb(dbh)
@@ -495,46 +530,12 @@ func (f filesystem) Copy(src Resource, target string, id uuid.UUID, recursive, o
return err
}
}
var tree []db.ReadDirRow
if recursive && src.Dir {
var err error
tree, err = f.db.ReadDir(f.ctx, db.ReadDirParams{ID: src.ID, IncludeRoot: false, Recursive: true})
if err != nil {
return err
}
}
dest, err = f.CreateMemberResource(destParent, id, destName, src.Dir)
if err != nil {
return err
}
if !src.Dir {
copy[src.ID] = id
}
ids := make(map[string]uuid.UUID)
ids[""] = dest.ID
for _, src := range tree {
id := uuid.New()
parent := ids[src.Path[0:strings.LastIndex(src.Path, "/")]]
if _, err := dbh.CreateResource(f.ctx, db.CreateResourceParams{ID: id, Parent: &parent, Name: src.Name, Dir: src.Dir}); err != nil {
if strings.Contains(err.Error(), "unique_member_resource_name") {
return ErrResourceNameConflict
}
if strings.Contains(err.Error(), "resources_pkey") {
return ErrResourceIDConflict
}
return err
} else {
if src.Dir {
ids[src.Path] = id
} else {
copy[src.ID] = id
}
}
}
return nil
_, err := dbh.CreateResources(f.ctx, create)
return err
})
if e == nil {

View File

@@ -0,0 +1,47 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.26.0
// source: copyfrom.go
package db
import (
"context"
)
// iteratorForCreateResources implements pgx.CopyFromSource.
type iteratorForCreateResources struct {
rows []CreateResourcesParams
skippedFirstNextCall bool
}
func (r *iteratorForCreateResources) Next() bool {
if len(r.rows) == 0 {
return false
}
if !r.skippedFirstNextCall {
r.skippedFirstNextCall = true
return true
}
r.rows = r.rows[1:]
return len(r.rows) > 0
}
func (r iteratorForCreateResources) Values() ([]interface{}, error) {
return []interface{}{
r.rows[0].ID,
r.rows[0].Parent,
r.rows[0].Name,
r.rows[0].Dir,
r.rows[0].ContentType,
r.rows[0].ContentSha256,
}, nil
}
func (r iteratorForCreateResources) Err() error {
return nil
}
func (q *Queries) CreateResources(ctx context.Context, arg []CreateResourcesParams) (int64, error) {
return q.db.CopyFrom(ctx, []string{"resources"}, []string{"id", "parent", "name", "dir", "content_type", "content_sha256"}, &iteratorForCreateResources{rows: arg})
}

View File

@@ -15,6 +15,7 @@ type DBTX interface {
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
QueryRow(context.Context, string, ...interface{}) pgx.Row
CopyFrom(ctx context.Context, tableName pgx.Identifier, columnNames []string, rowSrc pgx.CopyFromSource) (int64, error)
}
func New(db DBTX) *Queries {

View File

@@ -80,6 +80,15 @@ func (q *Queries) CreateResource(ctx context.Context, arg CreateResourceParams)
return i, err
}
type CreateResourcesParams struct {
ID uuid.UUID
Parent uuid.UUID
Name string
Dir bool
ContentType string
ContentSha256 string
}
const deleteRecursive = `-- name: DeleteRecursive :many
WITH RECURSIVE nodes(id, parent) AS (
SELECT r.id, r.parent

View File

@@ -7,6 +7,13 @@ INSERT INTO resources(
CASE @dir WhEN TRUE THEN '' ELSE 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855' END
) RETURNING *;
-- name: CreateResources :copyfrom
INSERT INTO resources(
id, parent, name, dir, content_type, content_sha256
) VALUES (
@id::uuid, @parent::uuid, @name::text, @dir::boolean, @content_type::text, @content_sha256::text
);
-- name: UpdateResourceContents :exec
UPDATE resources
SET