mirror of
https://codeberg.org/shroff/phylum.git
synced 2026-02-18 03:28:53 -06:00
[server][core] use copyfrom to bulk-insert rows
This commit is contained in:
@@ -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 {
|
||||
|
||||
47
server/internal/db/copyfrom.go
Normal file
47
server/internal/db/copyfrom.go
Normal 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})
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user