// Code generated by sqlc. DO NOT EDIT. // versions: // sqlc v1.27.0 // source: batch.sql package repository import ( "context" "github.com/google/uuid" "github.com/jackc/pgx/v5/pgtype" ) const addFailedFilename = `-- name: AddFailedFilename :exec UPDATE batch_uploads SET failed_filenames = failed_filenames || jsonb_build_array($2::text) WHERE id = $1 ` type AddFailedFilenameParams struct { ID uuid.UUID `db:"id"` Column2 string `db:"column_2"` } // AddFailedFilename // // UPDATE batch_uploads // SET failed_filenames = failed_filenames || jsonb_build_array($2::text) // WHERE id = $1 func (q *Queries) AddFailedFilename(ctx context.Context, arg *AddFailedFilenameParams) error { _, err := q.db.Exec(ctx, addFailedFilename, arg.ID, arg.Column2) return err } const countAcceptedBatchOutcomes = `-- name: CountAcceptedBatchOutcomes :one SELECT COUNT(*)::int FROM batch_document_outcomes WHERE batch_id = $1 AND outcome IN ('clean_passed', 'sync_skipped') ` // CountAcceptedBatchOutcomes // // SELECT COUNT(*)::int // FROM batch_document_outcomes // WHERE batch_id = $1 // AND outcome IN ('clean_passed', 'sync_skipped') func (q *Queries) CountAcceptedBatchOutcomes(ctx context.Context, batchID uuid.UUID) (int32, error) { row := q.db.QueryRow(ctx, countAcceptedBatchOutcomes, batchID) var column_1 int32 err := row.Scan(&column_1) return column_1, err } const countBatchOutcomes = `-- name: CountBatchOutcomes :one SELECT COUNT(*)::int FROM batch_document_outcomes WHERE batch_id = $1 ` // CountBatchOutcomes // // SELECT COUNT(*)::int // FROM batch_document_outcomes // WHERE batch_id = $1 func (q *Queries) CountBatchOutcomes(ctx context.Context, batchID uuid.UUID) (int32, error) { row := q.db.QueryRow(ctx, countBatchOutcomes, batchID) var column_1 int32 err := row.Scan(&column_1) return column_1, err } const countDocumentsByBatchId = `-- name: CountDocumentsByBatchId :one SELECT COUNT(*) as count FROM documents WHERE batch_id = $1 ` // CountDocumentsByBatchId // // SELECT COUNT(*) as count // FROM documents // WHERE batch_id = $1 func (q *Queries) CountDocumentsByBatchId(ctx context.Context, batchID *uuid.UUID) (int64, error) { row := q.db.QueryRow(ctx, countDocumentsByBatchId, batchID) var count int64 err := row.Scan(&count) return count, err } const countNonTerminalBatchOutcomes = `-- name: CountNonTerminalBatchOutcomes :one SELECT COUNT(*)::int FROM batch_document_outcomes WHERE batch_id = $1 AND outcome IN ('submitted', 'init_complete', 'sync_complete') ` // CountNonTerminalBatchOutcomes // // SELECT COUNT(*)::int // FROM batch_document_outcomes // WHERE batch_id = $1 // AND outcome IN ('submitted', 'init_complete', 'sync_complete') func (q *Queries) CountNonTerminalBatchOutcomes(ctx context.Context, batchID uuid.UUID) (int32, error) { row := q.db.QueryRow(ctx, countNonTerminalBatchOutcomes, batchID) var column_1 int32 err := row.Scan(&column_1) return column_1, err } const createBatchUpload = `-- name: CreateBatchUpload :one INSERT INTO batch_uploads (client_id, original_filename, total_documents) VALUES ($1, $2, $3) RETURNING id ` type CreateBatchUploadParams struct { ClientID string `db:"client_id"` OriginalFilename string `db:"original_filename"` TotalDocuments int32 `db:"total_documents"` } // CreateBatchUpload // // INSERT INTO batch_uploads (client_id, original_filename, total_documents) // VALUES ($1, $2, $3) RETURNING id func (q *Queries) CreateBatchUpload(ctx context.Context, arg *CreateBatchUploadParams) (uuid.UUID, error) { row := q.db.QueryRow(ctx, createBatchUpload, arg.ClientID, arg.OriginalFilename, arg.TotalDocuments) var id uuid.UUID err := row.Scan(&id) return id, err } const createBatchUploadWithStorage = `-- name: CreateBatchUploadWithStorage :one INSERT INTO batch_uploads ( client_id, original_filename, total_documents, status, archive_bucket, archive_key, file_size_bytes ) VALUES ($1, $2, $3, $4::batch_status, $5, $6, $7) RETURNING id, created_at ` type CreateBatchUploadWithStorageParams struct { ClientID string `db:"client_id"` OriginalFilename string `db:"original_filename"` TotalDocuments int32 `db:"total_documents"` Column4 BatchStatus `db:"column_4"` ArchiveBucket *string `db:"archive_bucket"` ArchiveKey *string `db:"archive_key"` FileSizeBytes *int64 `db:"file_size_bytes"` } type CreateBatchUploadWithStorageRow struct { ID uuid.UUID `db:"id"` CreatedAt pgtype.Timestamp `db:"created_at"` } // CreateBatchUploadWithStorage // // INSERT INTO batch_uploads ( // client_id, // original_filename, // total_documents, // status, // archive_bucket, // archive_key, // file_size_bytes // ) VALUES ($1, $2, $3, $4::batch_status, $5, $6, $7) // RETURNING id, created_at func (q *Queries) CreateBatchUploadWithStorage(ctx context.Context, arg *CreateBatchUploadWithStorageParams) (*CreateBatchUploadWithStorageRow, error) { row := q.db.QueryRow(ctx, createBatchUploadWithStorage, arg.ClientID, arg.OriginalFilename, arg.TotalDocuments, arg.Column4, arg.ArchiveBucket, arg.ArchiveKey, arg.FileSizeBytes, ) var i CreateBatchUploadWithStorageRow err := row.Scan(&i.ID, &i.CreatedAt) return &i, err } const detachRejectedBatchDocumentUploadsFromCandidateFolders = `-- name: DetachRejectedBatchDocumentUploadsFromCandidateFolders :execrows UPDATE documentUploads du SET folder_id = NULL WHERE du.batch_id = $1 AND du.folder_id IS NOT NULL AND EXISTS ( SELECT 1 FROM batch_folder_candidates bfc WHERE bfc.batch_id = $1 AND bfc.folder_id = du.folder_id ) AND EXISTS ( SELECT 1 FROM batch_document_outcomes bdo WHERE bdo.batch_id = $1 AND bdo.filename = du.filename AND ( bdo.outcome IN ( 'duplicate', 'init_duplicate', 'invalid_type', 'failed_open', 'failed_read', 'failed_s3_upload', 'failed_upload', 'clean_failed' ) OR ($2::boolean AND bdo.outcome IN ('submitted', 'init_complete', 'sync_complete')) ) ) ` type DetachRejectedBatchDocumentUploadsFromCandidateFoldersParams struct { BatchID *uuid.UUID `db:"batch_id"` IncludeNonterminal bool `db:"include_nonterminal"` } // @sqlc-vet-disable // // UPDATE documentUploads du // SET folder_id = NULL // WHERE du.batch_id = $1 // AND du.folder_id IS NOT NULL // AND EXISTS ( // SELECT 1 // FROM batch_folder_candidates bfc // WHERE bfc.batch_id = $1 // AND bfc.folder_id = du.folder_id // ) // AND EXISTS ( // SELECT 1 // FROM batch_document_outcomes bdo // WHERE bdo.batch_id = $1 // AND bdo.filename = du.filename // AND ( // bdo.outcome IN ( // 'duplicate', // 'init_duplicate', // 'invalid_type', // 'failed_open', // 'failed_read', // 'failed_s3_upload', // 'failed_upload', // 'clean_failed' // ) // OR ($2::boolean AND bdo.outcome IN ('submitted', 'init_complete', 'sync_complete')) // ) // ) func (q *Queries) DetachRejectedBatchDocumentUploadsFromCandidateFolders(ctx context.Context, arg *DetachRejectedBatchDocumentUploadsFromCandidateFoldersParams) (int64, error) { result, err := q.db.Exec(ctx, detachRejectedBatchDocumentUploadsFromCandidateFolders, arg.BatchID, arg.IncludeNonterminal) if err != nil { return 0, err } return result.RowsAffected(), nil } const detachRejectedBatchDocumentsFromCandidateFolders = `-- name: DetachRejectedBatchDocumentsFromCandidateFolders :execrows UPDATE documents d SET folderId = NULL WHERE d.batch_id = $1 AND d.folderId IS NOT NULL AND EXISTS ( SELECT 1 FROM batch_folder_candidates bfc WHERE bfc.batch_id = $1 AND bfc.folder_id = d.folderId ) AND EXISTS ( SELECT 1 FROM batch_document_outcomes bdo WHERE bdo.batch_id = $1 AND bdo.document_id = d.id AND ( bdo.outcome IN ( 'duplicate', 'init_duplicate', 'invalid_type', 'failed_open', 'failed_read', 'failed_s3_upload', 'failed_upload', 'clean_failed' ) OR ($2::boolean AND bdo.outcome IN ('submitted', 'init_complete', 'sync_complete')) ) ) ` type DetachRejectedBatchDocumentsFromCandidateFoldersParams struct { BatchID *uuid.UUID `db:"batch_id"` IncludeNonterminal bool `db:"include_nonterminal"` } // @sqlc-vet-disable // // UPDATE documents d // SET folderId = NULL // WHERE d.batch_id = $1 // AND d.folderId IS NOT NULL // AND EXISTS ( // SELECT 1 // FROM batch_folder_candidates bfc // WHERE bfc.batch_id = $1 // AND bfc.folder_id = d.folderId // ) // AND EXISTS ( // SELECT 1 // FROM batch_document_outcomes bdo // WHERE bdo.batch_id = $1 // AND bdo.document_id = d.id // AND ( // bdo.outcome IN ( // 'duplicate', // 'init_duplicate', // 'invalid_type', // 'failed_open', // 'failed_read', // 'failed_s3_upload', // 'failed_upload', // 'clean_failed' // ) // OR ($2::boolean AND bdo.outcome IN ('submitted', 'init_complete', 'sync_complete')) // ) // ) func (q *Queries) DetachRejectedBatchDocumentsFromCandidateFolders(ctx context.Context, arg *DetachRejectedBatchDocumentsFromCandidateFoldersParams) (int64, error) { result, err := q.db.Exec(ctx, detachRejectedBatchDocumentsFromCandidateFolders, arg.BatchID, arg.IncludeNonterminal) if err != nil { return 0, err } return result.RowsAffected(), nil } const getBatchUpload = `-- name: GetBatchUpload :one SELECT id, client_id, original_filename, total_documents, processed_documents, failed_documents, invalid_type_documents, status, progress_percent, failed_filenames, created_at, completed_at FROM batch_uploads WHERE id = $1 AND client_id = $2 ` type GetBatchUploadParams struct { ID uuid.UUID `db:"id"` ClientID string `db:"client_id"` } type GetBatchUploadRow struct { ID uuid.UUID `db:"id"` ClientID string `db:"client_id"` OriginalFilename string `db:"original_filename"` TotalDocuments int32 `db:"total_documents"` ProcessedDocuments int32 `db:"processed_documents"` FailedDocuments int32 `db:"failed_documents"` InvalidTypeDocuments int32 `db:"invalid_type_documents"` Status BatchStatus `db:"status"` ProgressPercent int32 `db:"progress_percent"` FailedFilenames []byte `db:"failed_filenames"` CreatedAt pgtype.Timestamp `db:"created_at"` CompletedAt pgtype.Timestamp `db:"completed_at"` } // GetBatchUpload // // SELECT id, client_id, original_filename, total_documents, processed_documents, // failed_documents, invalid_type_documents, status, progress_percent, // failed_filenames, created_at, completed_at // FROM batch_uploads // WHERE id = $1 AND client_id = $2 func (q *Queries) GetBatchUpload(ctx context.Context, arg *GetBatchUploadParams) (*GetBatchUploadRow, error) { row := q.db.QueryRow(ctx, getBatchUpload, arg.ID, arg.ClientID) var i GetBatchUploadRow err := row.Scan( &i.ID, &i.ClientID, &i.OriginalFilename, &i.TotalDocuments, &i.ProcessedDocuments, &i.FailedDocuments, &i.InvalidTypeDocuments, &i.Status, &i.ProgressPercent, &i.FailedFilenames, &i.CreatedAt, &i.CompletedAt, ) return &i, err } const getBatchUploadWithStorage = `-- name: GetBatchUploadWithStorage :one SELECT id, client_id, original_filename, total_documents, processed_documents, failed_documents, invalid_type_documents, status, archive_bucket, archive_key, file_size_bytes, failed_filenames, created_at, completed_at FROM batch_uploads WHERE id = $1 AND client_id = $2 ` type GetBatchUploadWithStorageParams struct { ID uuid.UUID `db:"id"` ClientID string `db:"client_id"` } type GetBatchUploadWithStorageRow struct { ID uuid.UUID `db:"id"` ClientID string `db:"client_id"` OriginalFilename string `db:"original_filename"` TotalDocuments int32 `db:"total_documents"` ProcessedDocuments int32 `db:"processed_documents"` FailedDocuments int32 `db:"failed_documents"` InvalidTypeDocuments int32 `db:"invalid_type_documents"` Status BatchStatus `db:"status"` ArchiveBucket *string `db:"archive_bucket"` ArchiveKey *string `db:"archive_key"` FileSizeBytes *int64 `db:"file_size_bytes"` FailedFilenames []byte `db:"failed_filenames"` CreatedAt pgtype.Timestamp `db:"created_at"` CompletedAt pgtype.Timestamp `db:"completed_at"` } // GetBatchUploadWithStorage // // SELECT id, client_id, original_filename, total_documents, // processed_documents, failed_documents, invalid_type_documents, // status, archive_bucket, archive_key, file_size_bytes, // failed_filenames, created_at, completed_at // FROM batch_uploads // WHERE id = $1 AND client_id = $2 func (q *Queries) GetBatchUploadWithStorage(ctx context.Context, arg *GetBatchUploadWithStorageParams) (*GetBatchUploadWithStorageRow, error) { row := q.db.QueryRow(ctx, getBatchUploadWithStorage, arg.ID, arg.ClientID) var i GetBatchUploadWithStorageRow err := row.Scan( &i.ID, &i.ClientID, &i.OriginalFilename, &i.TotalDocuments, &i.ProcessedDocuments, &i.FailedDocuments, &i.InvalidTypeDocuments, &i.Status, &i.ArchiveBucket, &i.ArchiveKey, &i.FileSizeBytes, &i.FailedFilenames, &i.CreatedAt, &i.CompletedAt, ) return &i, err } const getDocumentsByBatchId = `-- name: GetDocumentsByBatchId :many SELECT id, clientId, hash FROM documents WHERE batch_id = $1 ` type GetDocumentsByBatchIdRow struct { ID uuid.UUID `db:"id"` Clientid string `db:"clientid"` Hash string `db:"hash"` } // GetDocumentsByBatchId // // SELECT id, clientId, hash // FROM documents // WHERE batch_id = $1 func (q *Queries) GetDocumentsByBatchId(ctx context.Context, batchID *uuid.UUID) ([]*GetDocumentsByBatchIdRow, error) { rows, err := q.db.Query(ctx, getDocumentsByBatchId, batchID) if err != nil { return nil, err } defer rows.Close() items := []*GetDocumentsByBatchIdRow{} for rows.Next() { var i GetDocumentsByBatchIdRow if err := rows.Scan(&i.ID, &i.Clientid, &i.Hash); err != nil { return nil, err } items = append(items, &i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const getUnprocessedBatches = `-- name: GetUnprocessedBatches :many SELECT id, client_id, original_filename, total_documents, processed_documents, failed_documents, invalid_type_documents, status, progress_percent, created_at, completed_at FROM batch_uploads WHERE status = 'processing' ORDER BY created_at ASC ` type GetUnprocessedBatchesRow struct { ID uuid.UUID `db:"id"` ClientID string `db:"client_id"` OriginalFilename string `db:"original_filename"` TotalDocuments int32 `db:"total_documents"` ProcessedDocuments int32 `db:"processed_documents"` FailedDocuments int32 `db:"failed_documents"` InvalidTypeDocuments int32 `db:"invalid_type_documents"` Status BatchStatus `db:"status"` ProgressPercent int32 `db:"progress_percent"` CreatedAt pgtype.Timestamp `db:"created_at"` CompletedAt pgtype.Timestamp `db:"completed_at"` } // GetUnprocessedBatches // // SELECT id, client_id, original_filename, total_documents, // processed_documents, failed_documents, invalid_type_documents, // status, progress_percent, created_at, completed_at // FROM batch_uploads // WHERE status = 'processing' // ORDER BY created_at ASC func (q *Queries) GetUnprocessedBatches(ctx context.Context) ([]*GetUnprocessedBatchesRow, error) { rows, err := q.db.Query(ctx, getUnprocessedBatches) if err != nil { return nil, err } defer rows.Close() items := []*GetUnprocessedBatchesRow{} for rows.Next() { var i GetUnprocessedBatchesRow if err := rows.Scan( &i.ID, &i.ClientID, &i.OriginalFilename, &i.TotalDocuments, &i.ProcessedDocuments, &i.FailedDocuments, &i.InvalidTypeDocuments, &i.Status, &i.ProgressPercent, &i.CreatedAt, &i.CompletedAt, ); err != nil { return nil, err } items = append(items, &i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const insertBatchDocumentOutcome = `-- name: InsertBatchDocumentOutcome :exec INSERT INTO batch_document_outcomes (batch_id, filename, outcome, error_detail, document_id) VALUES ($1, $2, $3::batch_outcome_status, $4, $5) ON CONFLICT (batch_id, filename) DO UPDATE SET outcome = EXCLUDED.outcome, error_detail = EXCLUDED.error_detail, document_id = EXCLUDED.document_id, updated_at = NOW() ` type InsertBatchDocumentOutcomeParams struct { BatchID uuid.UUID `db:"batch_id"` Filename string `db:"filename"` Column3 BatchOutcomeStatus `db:"column_3"` ErrorDetail *string `db:"error_detail"` DocumentID *uuid.UUID `db:"document_id"` } // Upsert: if a row for this (batch_id, filename) already exists (e.g. batch // retry after partial failure), overwrite it with the latest outcome. // // INSERT INTO batch_document_outcomes (batch_id, filename, outcome, error_detail, document_id) // VALUES ($1, $2, $3::batch_outcome_status, $4, $5) // ON CONFLICT (batch_id, filename) DO UPDATE // SET outcome = EXCLUDED.outcome, // error_detail = EXCLUDED.error_detail, // document_id = EXCLUDED.document_id, // updated_at = NOW() func (q *Queries) InsertBatchDocumentOutcome(ctx context.Context, arg *InsertBatchDocumentOutcomeParams) error { _, err := q.db.Exec(ctx, insertBatchDocumentOutcome, arg.BatchID, arg.Filename, arg.Column3, arg.ErrorDetail, arg.DocumentID, ) return err } const listBatchDocumentOutcomes = `-- name: ListBatchDocumentOutcomes :many SELECT bdo.id, bdo.batch_id, bdo.filename, bdo.outcome, bdo.error_detail, bdo.document_id, bdo.created_at, bdo.updated_at, cce.fail as clean_fail FROM batch_document_outcomes bdo LEFT JOIN currentCleanEntries cce ON cce.documentId = bdo.document_id WHERE bdo.batch_id = $1 ORDER BY bdo.created_at ASC ` type ListBatchDocumentOutcomesRow struct { ID uuid.UUID `db:"id"` BatchID uuid.UUID `db:"batch_id"` Filename string `db:"filename"` Outcome BatchOutcomeStatus `db:"outcome"` ErrorDetail *string `db:"error_detail"` DocumentID *uuid.UUID `db:"document_id"` CreatedAt pgtype.Timestamp `db:"created_at"` UpdatedAt pgtype.Timestamp `db:"updated_at"` CleanFail NullCleanfailtype `db:"clean_fail"` } // Returns all outcome rows for a batch, with clean failure detail // joined from currentCleanEntries when applicable. // // SELECT // bdo.id, // bdo.batch_id, // bdo.filename, // bdo.outcome, // bdo.error_detail, // bdo.document_id, // bdo.created_at, // bdo.updated_at, // cce.fail as clean_fail // FROM batch_document_outcomes bdo // LEFT JOIN currentCleanEntries cce ON cce.documentId = bdo.document_id // WHERE bdo.batch_id = $1 // ORDER BY bdo.created_at ASC func (q *Queries) ListBatchDocumentOutcomes(ctx context.Context, batchID uuid.UUID) ([]*ListBatchDocumentOutcomesRow, error) { rows, err := q.db.Query(ctx, listBatchDocumentOutcomes, batchID) if err != nil { return nil, err } defer rows.Close() items := []*ListBatchDocumentOutcomesRow{} for rows.Next() { var i ListBatchDocumentOutcomesRow if err := rows.Scan( &i.ID, &i.BatchID, &i.Filename, &i.Outcome, &i.ErrorDetail, &i.DocumentID, &i.CreatedAt, &i.UpdatedAt, &i.CleanFail, ); err != nil { return nil, err } items = append(items, &i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listBatchFolderCandidates = `-- name: ListBatchFolderCandidates :many SELECT batch_id, folder_id, path, existed_before, created_at FROM batch_folder_candidates WHERE batch_id = $1 ORDER BY path ` // ListBatchFolderCandidates // // SELECT batch_id, folder_id, path, existed_before, created_at // FROM batch_folder_candidates // WHERE batch_id = $1 // ORDER BY path func (q *Queries) ListBatchFolderCandidates(ctx context.Context, batchID uuid.UUID) ([]*BatchFolderCandidate, error) { rows, err := q.db.Query(ctx, listBatchFolderCandidates, batchID) if err != nil { return nil, err } defer rows.Close() items := []*BatchFolderCandidate{} for rows.Next() { var i BatchFolderCandidate if err := rows.Scan( &i.BatchID, &i.FolderID, &i.Path, &i.ExistedBefore, &i.CreatedAt, ); err != nil { return nil, err } items = append(items, &i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listBatchUploads = `-- name: ListBatchUploads :many SELECT id, client_id, original_filename, total_documents, processed_documents, failed_documents, invalid_type_documents, status, progress_percent, created_at, completed_at FROM batch_uploads WHERE client_id = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3 ` type ListBatchUploadsParams struct { ClientID string `db:"client_id"` Limit int64 `db:"limit"` Offset int64 `db:"offset"` } type ListBatchUploadsRow struct { ID uuid.UUID `db:"id"` ClientID string `db:"client_id"` OriginalFilename string `db:"original_filename"` TotalDocuments int32 `db:"total_documents"` ProcessedDocuments int32 `db:"processed_documents"` FailedDocuments int32 `db:"failed_documents"` InvalidTypeDocuments int32 `db:"invalid_type_documents"` Status BatchStatus `db:"status"` ProgressPercent int32 `db:"progress_percent"` CreatedAt pgtype.Timestamp `db:"created_at"` CompletedAt pgtype.Timestamp `db:"completed_at"` } // ListBatchUploads // // SELECT id, client_id, original_filename, total_documents, processed_documents, // failed_documents, invalid_type_documents, status, progress_percent, // created_at, completed_at // FROM batch_uploads // WHERE client_id = $1 // ORDER BY created_at DESC // LIMIT $2 OFFSET $3 func (q *Queries) ListBatchUploads(ctx context.Context, arg *ListBatchUploadsParams) ([]*ListBatchUploadsRow, error) { rows, err := q.db.Query(ctx, listBatchUploads, arg.ClientID, arg.Limit, arg.Offset) if err != nil { return nil, err } defer rows.Close() items := []*ListBatchUploadsRow{} for rows.Next() { var i ListBatchUploadsRow if err := rows.Scan( &i.ID, &i.ClientID, &i.OriginalFilename, &i.TotalDocuments, &i.ProcessedDocuments, &i.FailedDocuments, &i.InvalidTypeDocuments, &i.Status, &i.ProgressPercent, &i.CreatedAt, &i.CompletedAt, ); err != nil { return nil, err } items = append(items, &i) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const listFolderCleanupReadyBatchIDs = `-- name: ListFolderCleanupReadyBatchIDs :many SELECT bu.id FROM batch_uploads bu WHERE bu.folder_cleanup_completed_at IS NULL AND bu.status IN ('completed', 'failed', 'cancelled') AND EXISTS ( SELECT 1 FROM batch_folder_candidates bfc WHERE bfc.batch_id = bu.id ) AND ( ( bu.total_documents > 0 AND (SELECT COUNT(*) FROM batch_document_outcomes bdo WHERE bdo.batch_id = bu.id) = bu.total_documents AND NOT EXISTS ( SELECT 1 FROM batch_document_outcomes bdo WHERE bdo.batch_id = bu.id AND bdo.outcome IN ('submitted', 'init_complete', 'sync_complete') ) ) OR ( bu.status IN ('failed', 'cancelled') AND (SELECT COUNT(*) FROM batch_document_outcomes bdo WHERE bdo.batch_id = bu.id) > 0 AND bu.completed_at IS NOT NULL AND bu.completed_at <= NOW() - ($1::int * INTERVAL '1 second') ) ) ORDER BY bu.created_at ASC LIMIT $2 ` type ListFolderCleanupReadyBatchIDsParams struct { StaleAfterSeconds int32 `db:"stale_after_seconds"` LimitCount int64 `db:"limit_count"` } // @sqlc-vet-disable // // SELECT bu.id // FROM batch_uploads bu // WHERE bu.folder_cleanup_completed_at IS NULL // AND bu.status IN ('completed', 'failed', 'cancelled') // AND EXISTS ( // SELECT 1 // FROM batch_folder_candidates bfc // WHERE bfc.batch_id = bu.id // ) // AND ( // ( // bu.total_documents > 0 // AND // (SELECT COUNT(*) FROM batch_document_outcomes bdo WHERE bdo.batch_id = bu.id) = bu.total_documents // AND NOT EXISTS ( // SELECT 1 // FROM batch_document_outcomes bdo // WHERE bdo.batch_id = bu.id // AND bdo.outcome IN ('submitted', 'init_complete', 'sync_complete') // ) // ) // OR ( // bu.status IN ('failed', 'cancelled') // AND (SELECT COUNT(*) FROM batch_document_outcomes bdo WHERE bdo.batch_id = bu.id) > 0 // AND bu.completed_at IS NOT NULL // AND bu.completed_at <= NOW() - ($1::int * INTERVAL '1 second') // ) // ) // ORDER BY bu.created_at ASC // LIMIT $2 func (q *Queries) ListFolderCleanupReadyBatchIDs(ctx context.Context, arg *ListFolderCleanupReadyBatchIDsParams) ([]uuid.UUID, error) { rows, err := q.db.Query(ctx, listFolderCleanupReadyBatchIDs, arg.StaleAfterSeconds, arg.LimitCount) if err != nil { return nil, err } defer rows.Close() items := []uuid.UUID{} for rows.Next() { var id uuid.UUID if err := rows.Scan(&id); err != nil { return nil, err } items = append(items, id) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const lockBatchUploadForFolderCleanup = `-- name: LockBatchUploadForFolderCleanup :one SELECT id, status, total_documents, created_at, completed_at, folder_cleanup_completed_at FROM batch_uploads WHERE id = $1 FOR UPDATE ` type LockBatchUploadForFolderCleanupRow struct { ID uuid.UUID `db:"id"` Status BatchStatus `db:"status"` TotalDocuments int32 `db:"total_documents"` CreatedAt pgtype.Timestamp `db:"created_at"` CompletedAt pgtype.Timestamp `db:"completed_at"` FolderCleanupCompletedAt pgtype.Timestamp `db:"folder_cleanup_completed_at"` } // LockBatchUploadForFolderCleanup // // SELECT id, status, total_documents, created_at, completed_at, folder_cleanup_completed_at // FROM batch_uploads // WHERE id = $1 // FOR UPDATE func (q *Queries) LockBatchUploadForFolderCleanup(ctx context.Context, batchID uuid.UUID) (*LockBatchUploadForFolderCleanupRow, error) { row := q.db.QueryRow(ctx, lockBatchUploadForFolderCleanup, batchID) var i LockBatchUploadForFolderCleanupRow err := row.Scan( &i.ID, &i.Status, &i.TotalDocuments, &i.CreatedAt, &i.CompletedAt, &i.FolderCleanupCompletedAt, ) return &i, err } const markBatchFolderCleanupCompleted = `-- name: MarkBatchFolderCleanupCompleted :exec UPDATE batch_uploads SET folder_cleanup_completed_at = NOW() WHERE id = $1 AND folder_cleanup_completed_at IS NULL ` // MarkBatchFolderCleanupCompleted // // UPDATE batch_uploads // SET folder_cleanup_completed_at = NOW() // WHERE id = $1 // AND folder_cleanup_completed_at IS NULL func (q *Queries) MarkBatchFolderCleanupCompleted(ctx context.Context, batchID uuid.UUID) error { _, err := q.db.Exec(ctx, markBatchFolderCleanupCompleted, batchID) return err } const recordBatchFolderCandidate = `-- name: RecordBatchFolderCandidate :exec INSERT INTO batch_folder_candidates (batch_id, folder_id, path, existed_before) VALUES ($1, $2, $3, $4) ON CONFLICT (batch_id, folder_id) DO UPDATE SET path = EXCLUDED.path, existed_before = batch_folder_candidates.existed_before AND EXCLUDED.existed_before ` type RecordBatchFolderCandidateParams struct { BatchID uuid.UUID `db:"batch_id"` FolderID uuid.UUID `db:"folder_id"` Path string `db:"path"` ExistedBefore bool `db:"existed_before"` } // Records a non-root folder touched by a batch upload. Once a batch observes a // folder as newly created, retries must preserve that fact. // // INSERT INTO batch_folder_candidates (batch_id, folder_id, path, existed_before) // VALUES ($1, $2, $3, $4) // ON CONFLICT (batch_id, folder_id) DO UPDATE // SET path = EXCLUDED.path, // existed_before = batch_folder_candidates.existed_before AND EXCLUDED.existed_before func (q *Queries) RecordBatchFolderCandidate(ctx context.Context, arg *RecordBatchFolderCandidateParams) error { _, err := q.db.Exec(ctx, recordBatchFolderCandidate, arg.BatchID, arg.FolderID, arg.Path, arg.ExistedBefore, ) return err } const resolveBatchDocumentOutcome = `-- name: ResolveBatchDocumentOutcome :exec UPDATE batch_document_outcomes SET document_id = $3, outcome = $4::batch_outcome_status, error_detail = $5, updated_at = NOW() WHERE batch_id = $1 AND filename = $2 AND document_id IS NULL ` type ResolveBatchDocumentOutcomeParams struct { BatchID uuid.UUID `db:"batch_id"` Filename string `db:"filename"` DocumentID *uuid.UUID `db:"document_id"` Column4 BatchOutcomeStatus `db:"column_4"` ErrorDetail *string `db:"error_detail"` } // Called by docInitRunner to set the document_id on a previously-submitted // outcome row and update the outcome to an init-stage result. // Finds the row by batch_id + filename since document_id is NULL at this point. // // UPDATE batch_document_outcomes // SET document_id = $3, // outcome = $4::batch_outcome_status, // error_detail = $5, // updated_at = NOW() // WHERE batch_id = $1 AND filename = $2 AND document_id IS NULL func (q *Queries) ResolveBatchDocumentOutcome(ctx context.Context, arg *ResolveBatchDocumentOutcomeParams) error { _, err := q.db.Exec(ctx, resolveBatchDocumentOutcome, arg.BatchID, arg.Filename, arg.DocumentID, arg.Column4, arg.ErrorDetail, ) return err } const setBatchCompletedAt = `-- name: SetBatchCompletedAt :exec UPDATE batch_uploads SET completed_at = $1 WHERE id = $2 ` type SetBatchCompletedAtParams struct { CompletedAt pgtype.Timestamp `db:"completed_at"` ID uuid.UUID `db:"id"` } // SetBatchCompletedAt // // UPDATE batch_uploads // SET completed_at = $1 // WHERE id = $2 func (q *Queries) SetBatchCompletedAt(ctx context.Context, arg *SetBatchCompletedAtParams) error { _, err := q.db.Exec(ctx, setBatchCompletedAt, arg.CompletedAt, arg.ID) return err } const setBatchTotalDocuments = `-- name: SetBatchTotalDocuments :exec UPDATE batch_uploads SET total_documents = $2 WHERE id = $1 ` type SetBatchTotalDocumentsParams struct { ID uuid.UUID `db:"id"` TotalDocuments int32 `db:"total_documents"` } // SetBatchTotalDocuments // // UPDATE batch_uploads SET total_documents = $2 WHERE id = $1 func (q *Queries) SetBatchTotalDocuments(ctx context.Context, arg *SetBatchTotalDocumentsParams) error { _, err := q.db.Exec(ctx, setBatchTotalDocuments, arg.ID, arg.TotalDocuments) return err } const updateBatchDocumentOutcomeByDocumentID = `-- name: UpdateBatchDocumentOutcomeByDocumentID :many UPDATE batch_document_outcomes SET outcome = $2::batch_outcome_status, error_detail = $3, updated_at = NOW() WHERE document_id = $1 AND outcome IN ('submitted', 'init_complete', 'sync_complete') RETURNING batch_id ` type UpdateBatchDocumentOutcomeByDocumentIDParams struct { DocumentID *uuid.UUID `db:"document_id"` Column2 BatchOutcomeStatus `db:"column_2"` ErrorDetail *string `db:"error_detail"` } // Updates the outcome for a document progressing through the pipeline. // Only updates rows in non-terminal pipeline states to prevent overwriting // terminal outcomes (e.g. a 'duplicate' row from a different batch that // shares the same document_id). // // UPDATE batch_document_outcomes // SET outcome = $2::batch_outcome_status, // error_detail = $3, // updated_at = NOW() // WHERE document_id = $1 // AND outcome IN ('submitted', 'init_complete', 'sync_complete') // RETURNING batch_id func (q *Queries) UpdateBatchDocumentOutcomeByDocumentID(ctx context.Context, arg *UpdateBatchDocumentOutcomeByDocumentIDParams) ([]uuid.UUID, error) { rows, err := q.db.Query(ctx, updateBatchDocumentOutcomeByDocumentID, arg.DocumentID, arg.Column2, arg.ErrorDetail) if err != nil { return nil, err } defer rows.Close() items := []uuid.UUID{} for rows.Next() { var batch_id uuid.UUID if err := rows.Scan(&batch_id); err != nil { return nil, err } items = append(items, batch_id) } if err := rows.Err(); err != nil { return nil, err } return items, nil } const updateBatchProgress = `-- name: UpdateBatchProgress :exec UPDATE batch_uploads SET processed_documents = $2, failed_documents = $3, invalid_type_documents = $4, progress_percent = $5 WHERE id = $1 ` type UpdateBatchProgressParams struct { ID uuid.UUID `db:"id"` ProcessedDocuments int32 `db:"processed_documents"` FailedDocuments int32 `db:"failed_documents"` InvalidTypeDocuments int32 `db:"invalid_type_documents"` ProgressPercent int32 `db:"progress_percent"` } // UpdateBatchProgress // // UPDATE batch_uploads // SET processed_documents = $2, // failed_documents = $3, // invalid_type_documents = $4, // progress_percent = $5 // WHERE id = $1 func (q *Queries) UpdateBatchProgress(ctx context.Context, arg *UpdateBatchProgressParams) error { _, err := q.db.Exec(ctx, updateBatchProgress, arg.ID, arg.ProcessedDocuments, arg.FailedDocuments, arg.InvalidTypeDocuments, arg.ProgressPercent, ) return err } const updateBatchStatus = `-- name: UpdateBatchStatus :exec UPDATE batch_uploads SET status = $2::batch_status, completed_at = CASE WHEN $2::batch_status IN ('completed', 'failed', 'cancelled') THEN NOW() ELSE NULL END WHERE id = $1 ` type UpdateBatchStatusParams struct { ID uuid.UUID `db:"id"` Column2 BatchStatus `db:"column_2"` } // UpdateBatchStatus // // UPDATE batch_uploads // SET status = $2::batch_status, // completed_at = CASE WHEN $2::batch_status IN ('completed', 'failed', 'cancelled') THEN NOW() ELSE NULL END // WHERE id = $1 func (q *Queries) UpdateBatchStatus(ctx context.Context, arg *UpdateBatchStatusParams) error { _, err := q.db.Exec(ctx, updateBatchStatus, arg.ID, arg.Column2) return err }